c++ - 为什么 `void* = 0` 和 `void* = nullptr` 会有所不同?

标签 c++ templates language-lawyer void-pointers nullptr

我在玩 SFINAE,发现我无法解释的行为。

这个 compiles fine :

template<typename Integer,
         std::enable_if_t<std::is_integral<Integer>::value>* = nullptr>
void foo(Integer) {}

template<typename Floating,
         std::enable_if_t<std::is_floating_point<Floating>::value>* = nullptr>
void foo(Floating) {}

虽然这个(nullptr 替换为 0):

template<typename Integer,
         std::enable_if_t<std::is_integral<Integer>::value>* = 0>
void foo(Integer) {}

template<typename Floating,
         std::enable_if_t<std::is_floating_point<Floating>::value>* = 0>
void foo(Floating) {}

gives me a compile error :

prog.cpp: In function ‘int main()’: prog.cpp:13:10: error: no matching function for call to ‘foo(int)’
     foo(3);
          ^ prog.cpp:5:6: note: candidate: template<class Integer, std::enable_if_t<std::is_integral<_Tp>::value>* <anonymous> > void foo(Integer)  void foo(Integer) {}
      ^~~ prog.cpp:5:6: note:   template argument deduction/substitution failed: prog.cpp:4:64: error: could not convert template argument ‘0’ to ‘std::enable_if_t<true, void>* {aka void*}’
          std::enable_if_t<std::is_integral<Integer>::value>* = 0>
                                                                ^ prog.cpp:9:6: note: candidate: template<class Floating, std::enable_if_t<std::is_floating_point<_Tp>::value>* <anonymous> > void foo(Floating)  void foo(Floating) {}
      ^~~ prog.cpp:9:6: note:   template argument deduction/substitution failed: prog.cpp:8:71: note: invalid template non-type parameter
          std::enable_if_t<std::is_floating_point<Floating>::value>* = 0>
                                                                       ^
当没有替换失败时,

enable_if_t 扩展为 void,所以我将在模板列表中添加类似 void* = 0 的内容参数。为什么它会破坏编译?..

最佳答案

默认模板参数遵循它们自己的更严格的转换规则。不应用 0 到指针类型的转换。

[temp.arg.nontype]/5.2 (强调我的):

for a non-type template-parameter of type pointer to object, qualification conversions ([conv.qual]) and the array-to-pointer conversion ([conv.array]) are applied; if the template-argument is of type std::nullptr_t, the null pointer conversion ([conv.ptr]) is applied.

[ Note: In particular, neither the null pointer conversion for a zero-valued integral constant expression ([conv.ptr]) nor the derived-to-base conversion ([conv.ptr]) are applied. Although 0 is a valid template-argument for a non-type template-parameter of integral type, it is not a valid template-argument for a non-type template-parameter of pointer type. However, both (int*)0 and nullptr are valid template-arguments for a non-type template-parameter of type “pointer to int.” — end note ]

关于c++ - 为什么 `void* = 0` 和 `void* = nullptr` 会有所不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50765742/

相关文章:

c++ - 10^10 - 10^11 范围内的数字的数据类型应该是什么?

c++ - 使另一个实例成为模板类的 friend

c - 使用指向 union 的不同元素的指针作为参数调用函数是未定义的行为吗?

c++ - 计算并显示二维数组中的出现次数

c++ - SSE4.1 与 gcc,如何拥有旧兼容代码?

css - 调整浏览器大小时 DIV 转到另一行

c++ - 函数参数列表中的类声明

c++ - 是明确的特化模板吗?

c++ - 将在设计器中创建的 QWidget 添加到 QToolbar

c++ - 从模板参数类型为新对象分配内存