为什么`void * = 0`和`void * = nullptr`会有所不同? [英] Why `void* = 0` and `void* = nullptr` makes the difference?

查看:213
本文介绍了为什么`void * = 0`和`void * = nullptr`会有所不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与SFINAE一起玩,发现我无法解释的行为.

I was playing with SFINAE and found behavior I cannot explain.

编译正常:

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) {}

给我一个编译错误:

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的内容.为什么会中断编译?.

enable_if_t expands to void when there are no substitution failures, so I will have something like void* = 0 among the list of template parameters. Why does it break compilation?..

推荐答案

默认模板参数遵循它们自己的转换规则,该规则更严格.

Default template arguments follow their own conversion rules, which are stricter. Conversion of 0 to a pointer type in particular, is not applied.

请参见 [temp.arg.nontype]/5.2 (强调我的意思):

See [temp.arg.nontype]/5.2 (emphasis mine):

对于类型为对象的指针的非类型模板参数,将应用限定转换([conv.qual])和数组到指针的转换([conv.array]);如果模板参数的类型为std::nullptr_t,则将应用空指针转换([conv.ptr]).

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.

[注意:特别是,零值整数常数表达式([conv.ptr])的空指针转换和派生基数转换([conv.ptr])都不是. ). 尽管0是整数类型的非类型模板参数的有效模板参数,但对于指针类型的非类型模板参数则不是有效的模板参数.(int*)0nullptr都是指向int的指针"类型的非类型模板参数的有效模板参数. —尾注]

[ 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 ]

这篇关于为什么`void * = 0`和`void * = nullptr`会有所不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆