3

メタプログラミングにまだ構造体とtypedefs (または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ますか?それとも、これはプログラマーの慣性の単なるケースですか?

4

1 に答える 1

3

関数のオーバーロードの使用に関するいくつかの問題を考えることができます。

異なるマッチング ルール。テンプレートの特殊化のリストは正確に一致するだけですが、関数のオーバーロードは、引数がパラメーターの型に変換できる場合に一致します。これは通常回避できますが、場合によってはより複雑なメタコードになる可能性があります。

戻り型の制限。関数は、関数(関数ポインタではない)、抽象クラス、コピー不可能な型(私は思う)、未知の境界の配列(おそらく)など、いくつかの型を返すことはできません。これは、型をテンプレート構造体にカプセル化することで回避できます。

typename一般に、一方ではとを使用usingし、他方ではdecltypeと ラッパー テンプレートを使用するというトレードオフが見られる可能性があります。

bool上記のコードは、トリックだけを排除するために、元のコードを改善したものであることに同意します。

于 2012-08-23T12:11:50.153 に答える