c – 返回类型与自动的模板特化和显式指定
考虑一下代码:
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发出错误:
Visual C同意(MSVC 19 2017 RTW):
gcc 8.2不编译任何代码(虽然原因可能是bug in C++17 support:
这里的正确解释是什么?我可以为不同的方法专业化使用不同的返回类型(为什么只有auto,但不能明确指定它们)?由于我对汽车和模板的理解有限,我会说“不”.我不明白为什么使用auto而不是显式命名返回类型允许不同的特殊化具有不同的返回类型. 但是,这些代码是我在elsewhere找到的代码的简化版本,所以也许我的解释是不正确的 – 在这种情况下,我会很感激解释为什么在auto用于特化时允许不同的返回类型,同时明确命名这种类型似乎是被禁止的. 解决方法
示例代码有几个不同的问题.
1)GCC未能实现CWG 727(在C 17中要求):https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282导致错误:非命名空间范围’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; } 它仍然表现出同样的错误.现在所有编译器都同意输出.他们编译foos并在bar专业化上出错.
如果特化还具有自动占位符,则标准允许使用自动返回类型来专门化函数
http://eel.is/c++draft/dcl.spec.auto#11 因此,这种专业化符合标准(类似于给定示例之一)并且在任何允许的地方都没有明确禁止. 至于bar的错误,标准说返回类型是函数模板签名的一部分:
http://eel.is/c++draft/defns.signature.templ 因此,在编译器的眼睛模板中<> int bar< 0>(){return 7; }是模板的专业化< ... N> int bar();模板(注意返回类型).但它之前未声明(专业化不能在声明之前),因此编译失败!如果添加模板< int N> int bar();然后它会编译(但如果你试图调用bar,则抱怨调用歧义). 基本上,你不能在专业化中改变函数签名,你只能专门化(duh)模板参数(它也应该与声明中的完全相同,因为它也是签名的一部分).
如上所述 – 您无法更改功能模板签名,这意味着您无法更改返回类型.但是,如果它取决于模板参数,您可以专门化返回类型! 考虑 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一起特化.但它仍然不会像使用汽车一样干净. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |