Почему `void * = 0` и` void * = nullptr` имеют значение? - PullRequest
0 голосов
/ 08 июня 2018

Я играл со SFINAE и обнаружил поведение, которое не могу объяснить.

Это прекрасно компилируется :

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 в списке параметров шаблона.Почему это нарушает компиляцию? ..

1 Ответ

0 голосов
/ 08 июня 2018

Аргументы шаблона по умолчанию следуют своим собственным правилам преобразования, которые являются более строгими.Преобразование 0 в тип указателя, в частности, не применяется.

См. [temp.arg.nontype] /5.2 (выделение мое):

для нетипового шаблона-параметра типа указатель на объект применяются квалификационные преобразования ([conv.qual]) и преобразование массива в указатель ([conv.array]);если аргумент шаблона имеет тип std::nullptr_t, применяется преобразование нулевого указателя ([conv.ptr]).

[ Примечание: В частности, ни преобразование нулевого указателя дляприменяется нулевое целочисленное константное выражение ([conv.ptr]) или преобразование из производной в основание ([conv.ptr]). Хотя 0 является допустимым аргументом шаблона для нетипового шаблона-параметра целого типа, он не является допустимым аргументом шаблона для нетипового шаблона-параметра типа указателя. Однако,(int*)0 и nullptr являются допустимыми аргументами шаблона для нетипового шаблона-параметра типа «указатель на int.» - примечание к концу]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...