2016-06-23 14 views
4

元のインスタンス化元のテンプレートを取得するにはどうすればよいですか?タイプがインスタンス化されたテンプレートを取得します

私は、次の操作を実行したいと思います:

struct Baz{}; 
struct Bar{}; 

template <typename T> 
struct Foo {}; 

using SomeType = Foo<Bar>; 

template <typename T> 
using Template = get_template<SomeType>::template type<T>; 

static_assert(std::is_same<Foo<Baz>, Template<Baz>>::value, ""); 

私は部分的な特殊化を介してこれを達成することができます知っているが、これは私がそれを使用するすべてのテンプレートのget_templateを専門とする私を強制的に:

template <typename T> 
struct get_template; 

template <typename T> 
struct get_template<Foo<T>> 
{ 
    template <typename X> 
    using type = Foo<X>; 
}; 

live example

この制限を回避する方法はありますか?

template <typename T> 
    struct get_template; 

template <template <class...> class Y, typename... Args> 
    struct get_template<Y<Args...>> { 
    template <typename... Others> 
    using type = Y<Others...>; 
    }; 

を次にテンプレートを取得する:あなたは(タイプ任意の数の引数でテンプレートのために働く必要があります)template template parameterを使用して、そのようなことを行うことができ

+0

親の種類を取得する可能性があります(http://stackoverflow.com/questions/31429363/get-the-type-of-a-parent) –

+3

この例は、あなたがエイリアスを使って"SomeType"は既に "Foo "( 'static_assert(std :: is_same > :: value、" ");')と同じです。実際に 'Foo'部分だけを回復しようとしているのは、別のタイプのインスタンスを生成したいからです。 – AndyG

+0

@AndyGはい私は最終的に別の型でインスタンス化したいと思っていましたが、私は質問を編集しました –

答えて

4

template <typename T> 
using Template = typename get_template<SomeType>::type<T>; 

として、コメントの中で@ Yakkが述べたように、上記は型引数だけを持つテンプレートに対してのみ機能します。あなたは:例えば、タイプと非型引数の特定のパターンとテンプレートの

// Note: You need the first size_t to avoid ambiguity with the first specialization 
template <template <class, size_t, size_t...> class Y, typename A, size_t... Sizes> 
    struct get_template<Y<A, Sizes...>> { 
    template <class U, size_t... OSizes> 
    using type = Y<U, OSizes...>; 
    }; 

を特化することができます...しかし、あなたは、任意のテンプレートのためにそれを特化することはできません。


DEMOFoostd::pair付き):

#include <type_traits> 
#include <map> 

struct Bar{}; 

template <typename T> 
struct Foo {}; 

using SomeType = Foo<Bar>; 

template <typename T> 
    struct get_template; 

template <template <class...> class Y, typename... Args> 
    struct get_template<Y<Args...>> { 
    template <typename... Others> 
    using type = Y<Others...>; 
    }; 

template <typename T> 
using Template = typename get_template<SomeType>::type<T>; 

static_assert(std::is_same<SomeType, Template<Bar>>::value, ""); 
static_assert(std::is_same<Foo<int>, Template<int>>::value, ""); 

using PairIntInt = std::pair<int, int>; 
using PairIntDouble = std::pair<int, double>; 

template <typename U1, typename U2> 
using HopeItIsPair = 
    typename get_template<PairIntDouble>::type<U1, U2>; 

static_assert(std::is_same<PairIntDouble, HopeItIsPair<int, double>>::value, ""); 
static_assert(std::is_same<PairIntInt, HopeItIsPair<int, int>>::value, ""); 
+0

当然、これは型を取るテンプレートまたは有限のテンプレートパターンに対してのみ機能します。 – Yakk

+0

@ Yakkはい...私はそれがどんな種類のテンプレートでも動作するようにする方法はないと思います(特に、インターリーブ型と非型のパラメータがある場合)。それにもかかわらず、テンプレートの引数パターンに関する情報がある場合は、上記のコードをニーズに合わせて簡単に変更できます。 – Holt

1

わからない私は質問を得ました。これは効果がありますか?

#include<type_traits> 
#include<utility> 

template<typename V, template<typename> class T, typename U> 
auto get_template(T<U>) { return T<V>{}; } 

struct Baz{}; 
struct Bar{}; 

template <typename T> 
struct Foo {}; 

using SomeType = Foo<Bar>; 

template <typename T> 
using Template = decltype(get_template<T>(SomeType{})); 

int main() { 
    static_assert(std::is_same<Foo<Baz>, Template<Baz>>::value, ""); 
} 

あなたは(SomeTypeは、例として、Templateのテンプレートパラメータかもしれない)、さらに一般化することができますが、それは仕方が何であるかのアイデアを提供します。

関連する問題