jal*_*alf 12 c++ templates visual-c++
我遇到了一些问题,将一些代码移植到MSVC,这让我很困惑.据我所知,代码应该是合法的,Clang编译它就好了.
我把它缩小到以下几点:
enum E {
x
};
template <typename T>
struct traits {
static const E val = x;
};
template <E e>
struct S {
S(){};
};
template <typename T>
S<traits<T>::val> foo(T t);
int main() {
char c = 0;
foo(c);
}
Run Code Online (Sandbox Code Playgroud)
请注意,在编译之后,代码会产生链接器错误(我删除了函数的定义foo以保持样本最小),但据我所知它应该干净地编译.
但是,MSVC给了我这个错误:
错误C2893:无法专门化函数模板'S :: val> foo(T)'
所以我的问题:
我在VC++ 2010和2012上重现了这个问题.
小智 3
经过我自己的一些测试,这似乎是 MSVC 中的编译器错误。traits<T>::val虽然它与 GCC 配合得很好,但当您尝试在模板参数内部使用返回值时,MSVC 会给出神秘且无用的编译器错误(与您问题中的错误相同)S< E e >。
有趣的是,当你改为S< E e >采用整数时,它就起作用了。考虑这个示例,与您的示例相同,但命名有所不同:
enum E {
x
};
template <typename T>
struct traits {
static const E val = x;
};
template <E e>
struct S {
S(){};
};
template <typename T>
S< traits<T>::val > tricky(T t) {
return S< traits<T>::val > ();
};
int main() {
char thiskidwhowalksaround = 0;
S<x> s = tricky( thiskidwhowalksaround );
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们只改变一件事:
template <int e> // int instead of E
struct S {
S(){};
};
Run Code Online (Sandbox Code Playgroud)
然后该程序会为我完美地编译(链接和运行)。如果你也恢复成原来的,然后E直接传入一个值,比如:
template <typename T>
S< x > tricky(T t) {
// ^ here
return S< x > (); // <-- here
};
Run Code Online (Sandbox Code Playgroud)
然后程序编译文件。MSVC 在尝试执行以下操作时遇到了问题:
traits<T>::val
哪里val有任何类型的枚举。我 99% 确定这是编译器本身的缺陷。这似乎是完全格式良好的 C++,所以我不能说 GCC 通过让原始代码片段工作而做了错误的事情或扩展。因此,我能收集到的最好信息是,与同类产品相比,MSVC 再次缺乏编译器的稳健性。
您可以停止阅读这里,因为现在我要花一点时间来抱怨 MSVC 编译器。
begin<rant>
这并不是说 VC++ 团队不好或者 C++ 不好,而是从我收集到的情况来看,截至撰写本文时,微软的编译器团队和标准库团队与其他部门相比规模很小。令我恼火的是,这样一种基础而重要的语言,也是微软行业核心的一部分,其人力相对较少,以至于在我短暂的一生中,它无法跟上我发现的世界上发展最慢的标准之一。我当然不是在批评 VC++ 团队的工作人员,但我深感困惑的是,为什么没有更多的人致力于让 C++ 不仅跟上速度,而且让编译器工作得更好,与其他编译器一样好产品领域。
end<rant>