SFINAE (Substitution Failure Is Not An Error)でSubstitutionを行う場所は関数のsignatureならどこでも使えるので、以下のように3種類(template引数、関数引数、戻り値)の書き方が可能です。
#include <iostream> #include <type_traits> #include <string> // 書き方1 (template引数) template <typename T, class = typename std::enable_if<std::is_fundamental<T>::value>::type> void f(T t) { std::cout << "fundamental type : " << t << std::endl; } template <typename T, class = typename std::enable_if<!std::is_fundamental<T>::value>::type> void f(const T& t) { std::cout << "not fundamental type : " << t << std::endl; } // 書き方2 (関数引数) template <typename T> void g(T t, typename std::enable_if<std::is_fundamental<T>::value>::type* = 0) { std::cout << "fundamental type : " << t << std::endl; } template <typename T> void g(const T& t, typename std::enable_if<!std::is_fundamental<T>::value>::type* = 0) { std::cout << "not fundamental type : " << t << std::endl; } // 書き方3 (戻り値) template <typename T> typename std::enable_if<std::is_fundamental<T>::value, void>::type h(T t) { std::cout << "fundamental type : " << t << std::endl; } template <typename T> typename std::enable_if<!std::is_fundamental<T>::value, void>::type h(const T& t) { std::cout << "not fundamental type : " << t << std::endl; } int main() { int a = 0; std::string str = "string"; f(a); // fundamental type : 0 f(str); // not fundamental type : string g(a); // fundamental type : 0 g(str); // not fundamental type : string h(a); // fundamental type : 0 h(str); // not fundamental type : string }
いずれも、std::enable_if
1番目のtemplate引数に与える方法では、無名のクラスにデフォルトtemplate引数を与えています。
2番目の引数に与える方法では、enable_ifのtypeのポインター型にヌルポインターのデフォルト引数を与えています。
3番目の戻り値を使う方法では、typename std::enable_if
どの書き方もWebや書籍で見たことがあるので、どれを使用するかは好みでいいのだと思います。
0 件のコメント:
コメントを投稿