メタプログラミングにまだ構造体とtypedef
s (またはs) を使用しているのはなぜですか?using
この質問のコードを見てください - 「make_function」のラムダまたは任意の呼び出し可能な呼び出し署名を推測する:
template<typename T> struct remove_class { };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)> { using type = R(A...); };
template<typename T, bool> struct get_signature_impl { };
template<typename R, typename... A>
struct get_signature_impl<R(A...), true> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(*)(A...), true> { using type = R(A...); };
template<typename T>
struct get_signature_impl<T, true> { using type = typename remove_class<
decltype(&std::remove_reference<T>::type::operator())>::type; };
bool
そのような奇妙なトリックがたくさんありtypename
ますstruct get_signature_impl;
.
C++11 でキーワードを取得したことは素晴らしいことですが、using
大きな違いはありません。
C++11 ではdecltype
、trailing-return-type があります。この力により、醜いメタ構造をすべて落とし、美しいメタ関数を書くことができます。
したがって、上記のコードを次のように書き換えることができます。
template<typename C, typename R, typename... A> auto make_function_aux(R(C::*)(A...)) -> std::function<R(A...)>;
template<typename C, typename R, typename... A> auto make_function_aux(R(C::*)(A...) const) -> std::function<R(A...)>;
template<typename R, typename... A> auto make_function_aux(R(A...)) -> std::function<R(A...)>;
template<typename R, typename... A> auto make_function_aux(R(*)(A...)) -> std::function<R(A...)>;
template<typename T> auto make_function_aux(const T&) -> decltype(make_function_aux(&T::operator()));
template<typename F> auto make_function(F&& f) -> decltype(make_function_aux(f)) { return decltype(make_function_aux(f))(std::forward<F>(f)); }
テンプレートの引数を一致させるために、テンプレートの部分的な特殊化が関数のオーバーロードよりも優れている状況はありdecltype
ますか?それとも、これはプログラマーの慣性の単なるケースですか?