Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带有非类型参数的奇怪模板实例化错误_C++_C++11_G++_Clang++_Compiler Bug - Fatal编程技术网

C++ 带有非类型参数的奇怪模板实例化错误

C++ 带有非类型参数的奇怪模板实例化错误,c++,c++11,g++,clang++,compiler-bug,C++,C++11,G++,Clang++,Compiler Bug,以下C++11代码使用g++4.7.4、g++4.8.5、g++4.9.3和g++5.3.0进行编译,但不使用clang++3.7.1或clang++3.8.0进行编译: template <typename F, F f> struct MetaValue {}; template <typename T> class IntSpec; template <int V> class IntSpec<MetaValue<int, V> &g

以下C++11代码使用g++4.7.4、g++4.8.5、g++4.9.3和g++5.3.0进行编译,但不使用clang++3.7.1或clang++3.8.0进行编译:

template <typename F, F f> struct MetaValue {};

template <typename T> class IntSpec;
template <int V> class IntSpec<MetaValue<int, V> > {};

// note: template is declared here:
template <typename T> class PtrSpec;
template <void * V> class PtrSpec<MetaValue<void *, V> > {};

int main() {
  IntSpec<MetaValue<int, 0> >();

  // implicit instantiation of undefined template 'PtrSpec<MetaValue<void *, nullptr> >'
  PtrSpec<MetaValue<void *, nullptr> >();
}
PtrSpec实例化时仅出现叮当错误,但IntSpec上没有。这是编译器错误,标准中的歧义还是我编写代码时需要考虑的问题?如果可能,请提供一份参考资料

编辑:我的进一步分析发现,以下两种编译器都适用:

template <typename F, F f> struct MetaValue {};

// note: template is declared here:
template<typename T> class PtrSpec;
template <int * V> class PtrSpec<MetaValue<int *, V> > {};

extern int x;

int main() { PtrSpec<MetaValue<int *, &x> >(); }

但是,如果我将&x更改为nullptr,我将使用clang++隐式实例化未定义的模板“PtrSpec”。

根据标准,此代码应该可以正常工作。发件人:

§14.3.2/1:

非类型、非模板参数的模板参数 应为以下各项之一:

[……]

计算为空指针值4.10的常量表达式;或 [……]

§14.3.2/5:

对用作表达式的每个表达式执行以下转换 非类型模板参数。如果无法使用非类型模板参数 转换为相应模板参数的类型,然后 程序格式不正确

[……]

对于指针指向对象类型的非类型模板参数, 限定转换4.4和数组到指针的转换 4.2适用;如果模板参数的类型为std::nullptr\t, 应用空指针转换4.10。[注:[…]但是,两者 int*0和nullptr是非类型的有效模板参数 类型为“指向整数的指针”的模板参数-结束注释] [……]


你知道为什么铿锵失败了吗?用铿锵归档一个bug。他们会想解决这个问题的。@Graznarak不,没有足够的动力。