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

标签 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 (trunk 254750) 进行编译:

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

Clang 仅在实例化 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> >(); }

但是如果我改变&xnullptr我得到implicit instantiation of undefined template 'PtrSpec<MetaValue<int *, nullptr> >'与 clang++。

最佳答案

这段代码应该可以正常工作,符合标准。来自 N3242 :

§14.3.2/1:

A template-argument for a non-type, non-template template-parameter shall be one of:

[...]

  • a constant expression that evaluates to a null pointer value (4.10); or

[...]

§14.3.2/5:

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.

[...]

  • for a non-type template-parameter of type pointer to object, qualification conversions (4.4) and the array-to-pointer conversion (4.2) are applied; if the template-argument is of type std::nullptr_t, the null pointer conversion (4.10) is applied. [Note: [...] However, both (int*)0 and nullptr are valid template-arguments for a non-type template-parameter of type “pointer to int.” — end note]

[...]

关于c++ - 带有非类型参数的奇怪模板实例化错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36033000/

相关文章:

c++ - list 和 forward_list 性能之间的区别?

java - 如何将 eclipse 从 "c/c++"更改为 "java"环境?

c++ - 关于将变量传递给 STL 容器并且不丢失它们超出范围

python - 使用 conda 在 WSL ubuntu 中安装 nes-py 时出现问题

c++ - 执行限定名称查找时 Clang 和 GCC 之间的不同行为

c++ - 减少将参数传递给函数所需的字符串流操作的冗长程度

C++ 11 正则表达式未按预期返回组

c++ - 调试断言失败(无效的空指针)默认字符串参数

c++ - 如何通过 KIT 编译收缩层次结构?

c++ - 没有匹配的函数来调用