在C 11中,如何使用decltype专门化一个使用“复杂”尾随返回类型声明的函数模板?以下在GCC中工作,但在VC2013中产生“错误C2912:显式特化'int f(void)'我不是函数模板的特化”:
#include <iostream>
int myint() { return 1; }
template<class T>
auto f() -> decltype(myint()) // this seems to cause problems
{
std::cout << "general\n";
return 1;
}
template <>
auto f<double>() -> decltype(myint())
{
std::cout << "special\n";
return 2;
}
int main()
{
f<int>();
f<double>(); // compiler error in VC, but not in GCC
}
我说"complicated"缺乏一个技术上精确的词,因为我不确定是什么产生了影响 . 例如,以下decltype,使用不依赖于任何函数结果类型的内置操作,适用于模板特化:
auto f() - > decltype(1 1)
所以,我的问题(都是相互关联的):
-
我的代码是否正确C 11?
-
这是一个VC错误吗?
-
如果这种专业化不起作用,我怎么能专门化std :: begin和std :: end(从而为不可更改的遗留容器类提供基于范围的for循环)?
1 回答
看起来对我来说不对 . 此外,用gcc和clang与
-Wall -Wextra
完全编译 .最有可能的 . VC在这方面臭名昭着,例如参见What exactly is "broken" with Microsoft Visual C++'s two-phase template instantiation?或google msvc two-phase lookup .
对于您提供的代码,解决方法是使用typedef:
所有三个主流编译器(gcc,clang,vs)似乎对这段代码感到满意 .
UPDATE:
在考虑之后,专门研究
std::begin()
和std::end()
将是我的最后手段 . 我的第一次尝试是提供成员begin()
和end()
功能;遗憾的是,它不适合您,因为您无法修改相应的代码 . 然后,我的第二次尝试是在我自己的命名空间中提供自由函数:如果您能够为容器专门化
std::begin()
和std::end()
,则此方法必须有效 . 如果你在全局命名空间中执行它(也就是说,你只是省略namespace my_namespace {
并关闭}
),它也可以工作,但我更喜欢将我的实现放入我自己的命名空间 .也可以看看
How to make my custom type to work with "range-based for loops"?
Why doesn't range-for find my overloads of begin and end for std::istream_iterator?