2013-03-17 111 views
12

我碰到一个问题,将一些代码移植到MSVC中,令我感到困惑。据我所知,代码应该是合法的,Clang编译它就好了。为什么MSVC无法编译这个模板函数?

我已经收窄到以下几点:

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); 
} 

注意,编译后的代码预计产量链接错误(我剥夺功能foo的定义保持样品最小),但据我所知应该干净地编译。

但是,MSVC给了我这个错误:

error C2893: Failed to specialize function template 'S::val> foo(T)'

所以我的问题:

  • 是MSVC在拒绝代码正确的机会吗? (如果是这样,为什么?)
  • 如果没有,任何人都可以缩小它做错了什么?如同它是否是一种他们根本没有实现的语言特性(比如模板的两阶段名称查找),或者“只是”他们声称支持的功能实现中的一个普通错误?

我转载的问题上VC++ 2010和2012年

+0

与今天早些时候的这个问题有关吗? [在类型推导之后,函数模板中的替换顺序是否有任何保证?](http://stackoverflow.com/questions/15462336/is-there-any-guarantee-on-the-order-of-substitution- in-a-function-template-after) – 2013-03-17 21:58:32

+0

@BoPersson:似乎与我无关。在这里,我想不出任何其他问题。顺便说一句,它在GCC 4.7.2 – 2013-03-17 22:04:56

+0

上按预期工作。而且,如果用'int'代替'enum',错误就会消失。它似乎是一个与'枚举'相关的错误 – 2013-03-17 22:05:36

回答

3

运行一些测试自己后,这似乎是在MSVC编译器错误。虽然GCC可以正常工作,但当您尝试在S< E e >返回的模板参数中使用traits<T>::val时,MSVC会给出神秘且无用的编译器错误(与您问题中的错误相同)。

有趣的是,当你改变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); 
} 

现在,我们只是改变一个单一的事情

template <int e> // int instead of E 
struct S { 
    S(){}; 
}; 

然后程序编译(链接和运行)完美地适合我。如果您也将恢复到原来的,然后在E值直接传递,如:

template <typename T> 
S<x> tricky(T t) { 
//^here 
    return S<x>(); // <-- here 
}; 

然后程序编译文件。 MSVC有它叮咬的灰尘在尝试做以下问题:

traits<T>::val

其中val是任何一种枚举。我99%肯定这是编译器本身的一个缺陷。这似乎是非常完美的C++,所以我不能说GCC通过使原始代码片段工作而做了错误或扩展-y。因此,我所能得到的最好结果是MSVC与同行相比缺乏编译器的稳健性。

您可以在这里停止阅读,因为现在我要花一点时间来咆哮有关MSVC编译器。

begin<rant> 这并不是说VC++团队是坏的,或者C++是坏的,但是从我搜集的编译器团队和标准库的团队在微软 - 作为写作的时间 - 是微小相比其他部门。令我感到震惊的是,MS行业这样一个基本而重要的语言和核心部分,其人力相对较少,无法跟上 - 在我短暂的一生中 - 我发现它是世界上最慢的移动标准之一。我当然不是要敲打在VC++团队中工作的人,但是我深感困惑,为什么他们没有更多的人努力让C++不仅速度快,而且使编译器的工作更好,并且与其他人一样好产品领域。 end<rant>

+0

这确实是一个编译器错误。我在[连接]上报告了它(https://connect.microsoft.com/VisualStudio/feedback/details/781537/failed-to-specialize-function-template#tabs),他们只是表示它将被修复为“in Visual C++的下一个版本“......每当这是 – jalf 2013-03-22 19:45:02

+0

@jalf:Hurray ......!也许。 – 2013-03-22 21:09:49

相关问题