enable_ifによりある条件のときだけtemplateを有効にすることができる。逆に言うとtemplateにしたくない条件を無効化することができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
// 5-example.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include <iostream> template<typename T> void myfunc(T t) { std::cout << t << "\n"; } template<typename T, typename = std::enable_if_t<std::is_convertible_v<T, int>>> void myintfunc(T t) { } template<typename T, typename = std::enable_if<std::is_convertible<T, int>::value>::type> void myintfunc_old(T t) { } int main() { myfunc('a'); myfunc(10); myfunc("hello"); myfunc(std::string("hello2")); myintfunc('a'); myintfunc(10); /* error C2672: 'myintfunc': no matching overloaded function found error C2783: 'void myintfunc(T)': could not deduce template argument for '<unnamed-symbol>' message : see declaration of 'myintfunc' */ // myintfunc("hello"); myintfunc_old('a'); myintfunc_old(10); // myintfunc_old("hello"); } |
std::enable_if_t<std::is_convertible_v<T, int>>はstd::enable_if<std::is_convertible<T, int>::value>::type>と同じことなのでこれについて考える。
全体としての意味はTがintに変換できるときだけテンプレートを有効にするということ。
is_convertible<T, int>はTがintに変換できるかを判定し、その結果はvalueに格納される。
enable_if<A>はAがtrueかどうかを判定し、trueならばtypeに型voidを格納する。falseならエラーになる。
よって全体としてTがintに変換できない場合はエラーになり、templateのインスタンス化は行われない(コンパイルエラーにはならない(SFINAE))。
この例ではどういうときにこれを使うのかの応用例は示せていないが、特定の型のときだけテンプレートを有効にしたい場合に使う。
typename = としているのはtypename A = などと同じでデフォルトのテンプレート引数の指定、これはテンプレートのインスタンス化をするかどうかだけのために使われるので、コード中では使われないのでこういう記述になっている。