- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
考虑代码:
class Test {
public:
template<int N> auto foo() {}
template<> auto foo<0>() { return 7; }
template<int N> void bar() {}
template<> int bar<0>() { return 7; }
};
我已经用不同的编译器测试了代码(通过 Compiler Explorer )。
如果 Clang 7.0.0 foo
编译,而 bar
给出错误:
:8:20: error: no function template matches function template specialization 'bar'
template<> int bar<0>() { return 7; }
^:7:26: note: candidate template ignored: could not match 'void ()' against 'int ()'
template<int N> void bar() {};
^
Visual C++ 同意(MSVC 19 2017 RTW):
(8): error C2912: explicit specialization 'int Test::bar(void)' is not a specialization of a function template
gcc 8.2 不编译任何代码(虽然原因可能是 bug in C++17 support :
:5:14: error: explicit specialization in non-namespace scope 'class Test'
template<> auto foo<0>() { return 7; };
^:5:28: error: template-id 'foo<0>' in declaration of primary template
template<> auto foo<0>() { return 7; };
^:7:26: error: too many template-parameter-lists
template<int N> void bar() {};
^~~:8:14: error: explicit specialization in non-namespace scope 'class Test'
template<> int bar<0>() { return 7; }
^:8:20: error: expected ';' at end of member declaration
template<> int bar<0>() { return 7; }
^~~
;:8:23: error: expected unqualified-id before '<' token
template<> int bar<0>() { return 7; }
^
这里正确的解释是什么?我可以为不同的方法特化设置不同的返回类型吗(以及为什么只使用 auto
,而不是在显式指定它们时)?由于我对 auto
和模板的理解有限,我会说“不”。我不明白为什么使用 auto
而不是显式命名返回类型允许不同的特化有不同的返回类型。
但是,这些代码是我找到的代码的简化版本 elsewhere ,所以也许我的解释是不正确的 - 在这种情况下,我将不胜感激解释 为什么当 auto
用于特化时允许不同的返回类型,而显式命名类型似乎是禁止。
最佳答案
示例代码存在几个不同的问题。
1) GCC 未能实现 CWG 727(C++17 要求):https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282这导致error: explicit specialization in non-namespace scope 'class Test'
2) 如果我们忽略它,示例代码可以简化为
template<int N> auto foo() {}
template<> auto foo<0>() { return 7; }
template<int N> void bar() {}
template<> int bar<0>() { return 7; }
仍然显示相同的错误。现在所有编译器都同意输出。他们编译foo
s 并在 bar
上出错特化。
why different return type is allowed when auto is used for specialization
标准允许使用 auto
来专门化函数如果特化也有 auto
则返回类型占位符
Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type
http://eel.is/c++draft/dcl.spec.auto#11
因此,由于这种特化符合标准(类似于给定的示例之一)并且在任何允许的地方都没有被明确禁止。
关于 bar
的错误,标准说返回类型是函数模板签名的一部分:
⟨function template⟩ name, parameter type list ([dcl.fct]), enclosing namespace (if any), return type, template-head, and trailing requires-clause ([dcl.decl]) (if any)
http://eel.is/c++draft/defns.signature.templ
因此,在编译器眼中template<> int bar<0>() { return 7; }
是 template<... N> int bar();
的特化模板(注意返回类型)。但它之前没有声明(特化不能先于声明)所以编译失败!如果添加 template<int N> int bar();
然后它会编译(但是如果你尝试调用 bar
会提示调用歧义)。
基本上,您不能在特化中更改函数签名,您只能特化 (duh) 模板参数(它也应该与声明中的完全相同,因为它也是签名的一部分)。
Can I have a template specialization with explicitly declared return type different from the base template at all
如前所述 - 您无法更改函数模板签名,这意味着您无法更改返回类型。但是,如果它依赖于模板参数,您可以专门化返回类型!
考虑
template<int N, typename R = void> R bar() {}
template<> int bar<0>() { return 7; }
// bar<0, int> is deduced, see: http://eel.is/c++draft/temp.expl.spec#10
这是允许的,但缺点是必须写 bar<0, int>
当您想调用特化电话时:https://godbolt.org/z/4lrL62
这可以通过在原始声明中将类型设为条件来解决:https://godbolt.org/z/i2aQ5Z
但是一旦专业数量增加,维护起来很快就会变得很麻烦。
另一个可能更易于维护的选项是返回类似 ret_type<N>::type
的内容并将其与 bar
一起专门化.但它仍然不会像使用 auto
那样干净。 .
关于c++ - 返回类型与自动的模板特化和显式规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52462111/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 4 年前。
正如您在 this travis.yml 中看到的那样文件,我的代码依赖于一些第三方库,我在构建项目之前将它们安装在远程系统上。 Travis 每次推送提交时都会下载并构建这些库,这可以避免吗?我的意
我是一名优秀的程序员,十分优秀!