#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
在这里是必要的?在这种情况下,我有两个方面的原因:
如果第二个模板参数是一个类型名,编译器可以推断出;因为我将它作为
class
加以宣传。即使编译器无法推断出它是否是类型名称,按照
SFINAE
规则,编译器不应该失败,因为未调用模板函数GetMyString
。
我的意思是'class = Something'明确指出'SomeThing'是一个类型名称。编译器应该知道这一点。 – xmllmx
@xmllmx:正如我上面所说的,在C++语言中没有“应该知道的”这样的事情。有语言规范说明什么是格式良好的代码,什么是不合格的代码。如果某些代码格式不正确,编译器必须报告它(并且通常无法编译它),即使对于您来说它可能看起来像编译器“应该知道”该怎么做。语言规范并没有说在这种情况下编译器应该算出来。相反,它说在这种情况下需要'typename'。 – AnT
如果C++标准要求在这里添加'typename',并且确实没有必要,那么我认为标准应该放松这个不必要的限制。 – xmllmx