私は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
のようなものがあります。なぜコンパイルが壊れるのですか?.
デフォルトのテンプレート引数は、より厳密な独自の変換規則に従います。特に0
からポインタ型への変換は適用されません。
[temp.arg.nontype] /5.2 (私の強調)を参照してください。
オブジェクトへのタイプポインターの非タイプテンプレートパラメーターの場合、修飾変換([conv.qual])と配列からポインターへの変換([conv.array])が適用されます。テンプレート引数のタイプが
std::nullptr_t
の場合、ヌルポインター変換([conv.ptr])が適用されます。[注:特に、ゼロ値の積分定数式([conv.ptr])のnullポインター変換も、派生からベースへの変換([conv。 ptr])が適用されます。
0
は、整数型の非タイプテンプレートパラメータの有効なテンプレート引数ですが、非タイプテンプレートパラメータの有効なテンプレート引数ではありませんポインタ型。ただし、(int*)0
とnullptr
はどちらも、「pointer to int」型の非型テンプレートパラメータの有効なテンプレート引数です。 —エンドノート]