11

条件に応じて2種類からテンプレートを選択してほしい。例えば

struct Base {};

template <typename T1, typename T2>
struct test
{
    // e.g. here it should select T1/T2 that is_base_of<Base>
    typename select_base<T1, T2>::type m_ValueOfBaseType;
};

もちろん、条件をselect_baseに渡す(汎用にする)ことは便利ですが、ハードコーディングされたソリューションの方が簡単で優れています。

これが私が試したサンプルソリューションですが、常にT1を選択します:http://ideone.com/EnVT8

問題は、select_baseテンプレートを実装する方法です。

4

2 に答える 2

18

@Matthieuが彼の回答で実装したクラステンプレートstd::conditionalの代わりに使用する場合、ソリューションは次のようになります。if_

template <typename T, typename U>
struct select_base
{
   typedef typename std::conditional<std::is_base_of<T, Base>::value, T, U>::type base_type;
};

または単にこれ:

template <typename T, typename U>
struct select_base : std::conditional<std::is_base_of<T, Base>::value, T, U> {};

これはさらに良く見えます。

これら2つのソリューションの違いは、最初のソリューションでは、私が付けたように、ネストされた型にプログラマーにわかりやすいbase_type名前を付けるのに対し、2番目のソリューションでは、ネストされた型はtypeプログラマーにわかりにくい名前になっていることです。 。

上記の両方のソリューションでは、ネストされたタイプをselect_base<T,U>::base_type(最初のソリューションで)またはselect_base<T,U>::type(2番目のソリューションで)使用する必要があることに注意してください。そのためtypename、質問自体。

ただし、代わりにテンプレートエイリアスを使用する場合は、次のように定義されます。

template<typename T, typename U>
using base_type = typename std::conditional<std::is_base_of<T, Base>::value, T, U>::type;

次にbase_type<T,U>、ネストされたタイプなしで、次のように使用できますtypename

template <typename T1, typename T2>
struct test
{
   //typename select_base<T1, T2>::type m_ValueOfBaseType; //ugly!

   base_type<T1, T2>  m_ValueOfBaseType; //better
};

お役に立てば幸いです。

于 2012-06-16T17:07:53.860 に答える
8

C ++ 14(およびそれ以降):

template <typename T, typename U>
struct select_base:
    std::conditional_t<std::is_base_of<T, Base>::value, T, U> {};

同じように、代わりにこれを使用できます。

template<typename T, typename U>
using select_base = std::conditional_t<std::is_base_of_v<T,Base>, T, U>;

これらの2つのアプローチの違いは、それらを使用するときに観察できます。たとえば、前者の場合は使用する必要がありますが::type、後者の場合は使用しません。また、依存型が最初のアプローチの使用に関係している場合はtypename、コンパイラーを支援するために、同様に使用する必要があります。2番目のアプローチは、そのようなノイズがすべてないため、この回答の他のアプローチよりも優れています。

また、C++11でも同様のタイプエイリアスを記述できることに注意してください。


C ++ 11

template <typename T, typename U>
struct select_base:
    std::conditional<std::is_base_of<T, Base>::value, T, U>::type {};
//                 ^                                       ^~~~~~

C ++ 98

条件付きは十分に簡単です:

template <typename bool, typename T, typename U>
struct conditional { typedef T type; };

template <typename T, typename U>
struct conditional<false, T, U> { typedef U type; };

is_base_of少し複雑ですが、Boostで実装が利用可能ですが、ここでは再現しません。

その後、C++11を参照してください。

于 2012-06-16T17:00:36.657 に答える