2013-10-15 21 views
0
#include <type_traits> 

using namespace std; 

template<class T> struct IsCharType   { enum { value = false }; };  
template<>  struct IsCharType<char> { enum { value = true }; };  
template<>  struct IsCharType<wchar_t> { enum { value = true }; }; 

template<class CharType, class = enable_if<IsCharType<CharType>::value>::type> 
struct MyString 
{ 
    MyString() 
    {} 

    MyString(CharType*) 
    {} 
}; 

template<class CharType> 
MyString<CharType> GetMyString(CharType* str) // error C2923 
{ 
    return MyString<CharType>(str); 
} 

int main() 
{} 

我的编译器是VC++ 2013 RC。上面的代码由于错误C2923而无法编译。即使模板类型被声明为`class`,为什么'typename`仍然是必需的?

错误C2923: '的MyString': '的std :: enable_if ::值,空隙> ::类型' 不是参数 '' 的有效 模板类型参数

然而,如果我改变

template<class CharType, class = enable_if<IsCharType<CharType>::value>::type> 

template<class CharType, class = typename enable_if<IsCharType<CharType>::value>::type> 

然后它会好的。

我只是想知道为什么typename在这里是必要的?在这种情况下,我有两个方面的原因:

  1. 如果第二个模板参数是一个类型名,编译器可以推断出;因为我将它作为class加以宣传。

  2. 即使编译器无法推断出它是否是类型名称,按照SFINAE规则,编译器不应该失败,因为未调用模板函数GetMyString

回答

1

您还没有将其声明为类。您的模板参数声明

class = enable_if<IsCharType<CharType>::value>::type 

是未命名类型参数的声明。我们可以给这个参数一个明确的名字,例如

class U = enable_if<IsCharType<CharType>::value>::type 

因此,在这种情况下,它是被声明为类型参数U(“为类”)。

同时,=右边的所有内容都没有“声明为类”。它由编译器根据一般规则进行解释,而不考虑它恰好是类型参数的默认参数。 “

逻辑”因为这是类型参数的默认参数,所以编译器必须自己认识到这是一个类型“在这里不适用,因为语言规范没有说它适用。此外,语言标准实际上说的

在模板声明或定义使用的名字,这是 依赖模板参数假定未命名类型,除非 适用的名称查找发现一个类型名称或该名称由关键字typename限定为 。

这意味着,编译器是假定是

enable_if<IsCharType<CharType>::value>::type 

一个类型,你希望它做的,这是违反所需

该语言确实有许多上下文,其中依赖名称被无条件假定为命名一个类型。这包括构造函数初始化列表,基类说明符和详细的类型说明符。但模板类型参数的默认参数不是这样的上下文之一。

SFINAE并不拯救这里的情况。顾名思义,SFINAE在替代时起作用。你的代码永远不会被替换,它会更早打破。这只是一个无效的模板定义。

+0

我的意思是'class = Something'明确指出'SomeThing'是一个类型名称。编译器应该知道这一点。 – xmllmx

+0

@xmllmx:正如我上面所说的,在C++语言中没有“应该知道的”这样的事情。有语言规范说明什么是格式良好的代码,什么是不合格的代码。如果某些代码格式不正确,编译器必须报告它(并且通常无法编译它),即使对于您来说它可能看起来像编译器“应该知道”该怎么做。语言规范并没有说在这种情况下编译器应该算出来。相反,它说在这种情况下需要'typename'。 – AnT

+0

如果C++标准要求在这里添加'typename',并且确实没有必要,那么我认为标准应该放松这个不必要的限制。 – xmllmx

相关问题