5

申し訳ありませんが、これはよくある質問のように聞こえます。私が見た限り、私の問題に対する答えが見つかりませんでした。最も近い投稿は次のとおりです:基本 POD のみのテンプレートの特殊化

classtemplate <class T> class A {...};があり、 operator+ を内部二項演算子 (型 A の 2 つのオブジェクト) として、および混合二項演算子 (型 A と数値 POD 型のオブジェクト) としてオーバーロードしたいとします。

理想的には、私が書きたいのは次のとおりです。

#include <type_traits>
using namespace std;

// Declare/fine template
template <class T> class A {...};

// Internal binary operator
template < class T, class U >
    A< typename common_type<T,U>::type >
operator+ ( const A<T> &a, const A<U> &a ) { ... }

// Mixed binary operator
template < class T, class U >
    A< typename common_type<T,U>::type >
operator+ ( const A<T> &a, const U &b ) { ... }

しかし、2 番目の定義は最初の定義と矛盾しているようです。2 番目の定義を使用して、U が数値 POD 型であることを確認する方法を知っていますが、それは重要ではありません。そのようにすると、問題は、それが A である場合に、U で囲まれている基になるテンプレートの型を知る方法がないことです。

私の質問が十分に明確でない場合は教えてください。事前に感謝します! :)

編集:テンプレートの仕様は、最後の文「U if it is some A<T>」で、HTML フィルターによって消去されました。要するに、T が隠されているということです。

4

2 に答える 2

2

A少しヘルパー トレイトを使用して、特殊化をより一般的な型と区別することができます。

#include <type_traits>


// "A" template    

template <typename> class A {};


// Traits for "A-ness":

template <typename> struct is_a : std::false_type { };
template <typename T> struct is_a<A<T>> : std::true_type { };


// Operators:

template <class T, class U>
A<typename std::common_type<T, U>::type>
operator+(const A<T> & a, const A<U> & b);

template <class T, class U,
          typename = typename std::enable_if<!is_a<U>::value>::type>
A<typename std::common_type<T, U>::type>
operator+(const A<T> & a, const U & b);

これにより、実行可能なセットから 2 番目のオーバーロードがすぐに除外されるため、最初のオーバーロードのみが必要な場合、2 番目のオーバーロードの戻り値の型を決定する問題は発生しません。

(これは、enable_ifデフォルトのテンプレート引数を使用してオーバーロード セットを制御する例です。)

于 2012-11-24T16:56:16.210 に答える
1

あなたはSFINAEにやさしいものを書くことができますcommon_type-私は個人的に、特性はほとんど常にSFINAEであるべきだというキャンプにいます。ウィットに:

// Black hole metafunction that eats everything
template<typename...> struct void_ { using type = void; };

template<typename... T>
using Void = typename void_<T...>::type;

// Due to std::common_type being variadic we need to
// pass a variadic pack around
template<typename... T> struct list {};

// Actually defined, but with no member types for SFINAE purposes
template<typename Sequence, typename Sfinae = void>
struct common_type_impl {};

template<typename... T>
struct common_type_impl<list<T...>, Void<typename std::common_type<T...>::type>>
: std::common_type<T...> {};

template<typename... T> struct common_type: common_type_impl<list<T...>> {};

A<T>これで、間に共通のタイプがなくU、過負荷が騒々しく文句を言うのではなく、候補のリストから削除されます。

DR 2141std::common_typeに記載されているように、計算結果に独自の問題があるため、完全に置き換えることもできます。より良い解決策が何であるかが明確でないため、私は代替品の概要を説明しません。特に、提案されているDRの解決策はより悪いと思います。

于 2012-11-25T09:40:34.130 に答える