2017-08-28 12 views
2

次のC++ 14のコードでは、バリアブルテンプレートを使用してPossibleTypesのコンテナを作成したいと考えています。次に、前に指定した型のメンバータプルを持つ別のコンテナを作成します。バリエーションの種類を再利用

これを行うにはどうすればいいですか? Fooにテンプレートのタイプのトピックと同じように< int、double>のタプルが含まれています。

事前に感謝します。

#include <iostream> 
#include <tuple> 
#include <type_traits> 

template <typename... T> 
struct PossibleTypes {}; 

PossibleTypes<int,double> topics; 

template <typename... T> 
struct Foo{ 
    std::tuple<T...> member; 
}; 

int main(){ 
    Foo<??(topics)??> x; 
    return 0; 
} 

答えて

10

これを行う方法は複数あります。それらをすべて理解する必要はなく、必要な機能を備えたものを見つけるだけです。

これを行うための3つの非常に異なる方法があります。インスタンスから

template<class Src, template<class...>class Dest> 
struct transcribe; 
template<class Src, template<class...>class Dest> 
using transcribe_t=typename transcribe<Src,Dest>::type; 

template<template<class...>class Src, class...Ts, template<class...>class Dest> 
struct transcribe<Src<Ts...>, Dest>{ 
    using type=Dest<Ts...>; 
}; 

、テンプレートに

議事録:

フー

を変更することによって侵入的

transcribe_t<decltype(topics), Foo> x; 

これもバンドルを取るFooを変更する代わりにすることによって侵入的に行うことができますパック。

template <class Bundle> 
struct Foo; 

template <typename... T> 
struct Foo<PossibleTypes<T...>>{ 
    std::tuple<T...> member; 
}; 

または

template <template<class...>class Z, typename... T> 
struct Foo<Z<T...>>{ 
    std::tuple<T...> member; 
}; 

その後:あなただけ...引数の1セットを渡していない場合ははるかに現実的なことができ

Foo<decltype(topics)> x; 

価値ベースのメタプログラミング

我々はまた、この使用して値ベースのメタプログラミングアプローチすることができます:私たちに与えて

template<class T> 
struct tag_t {constexpr tag_t(){} using type=T;}; 
template<class T> 
constexpr tag_t<T> tag{}; 
template<template<class...>class Z> 
struct ztemplate_t { 
    constexpr ztemplate_t() {} 
    template<class...Ts> using apply=Z<Ts...>; 
    template<class...Ts> 
    constexpr tag_t<Z<Ts...>> operator()(tag_t<Ts>...)const{ return {}; } 
}; 
template<template<class...>class Z> 
constexpr ztemplate_t<Z> ztemplate{}; 

template<class Tag> 
using type=typename Tag::type; 

template <class... T> 
struct PossibleTypes { 
    template<template<class...>class Z> 
    constexpr auto operator()(ztemplate_t<Z> z) const { 
    return z(tag<T>...); 
    } 
}; 

:かなり滑らかなのである

int main(){ 
    type<decltype(topics(ztemplate<Foo>)) > x; 
    return 0; 
} 

を。 Live example

tagは、型を値に持ち上げます。 ztemplateは、テンプレートを値にリフトします。

ztemplate<some_template>(tag<T0>, tag<T1>)

tag_t<some_template<T0, T1>>ようT0, T1some_templateを適用した結果のtagを返します。

タグからタイプに戻るには、type<decltype(some_tag_expression)>を実行します。

PossibleTypesには、PossibleTypesに保存されているタイプにテンプレートを適用するoperator()(ztemplate)も含まれています。

この種の狂気は、C++のバリューベースのプログラミングがテンプレート構文よりはるかに表現力豊かで扱いやすいため、ますますタイプベースの操作が増えるほどうまく機能します。

+0

@mihai上記のうちオブジェクトをインスタンス化する必要はありませんか?どのような場合でも、タイプを作成します。あなたのコードがしたので、私は型のインスタンスを作成します(それが機能することを証明するために、私は推測します)。 'x'を削除すると型表現があり、インスタンスはありません。 typedefを使用するか、またはを使用して名前を付けるなどしてください。 – Yakk

+0

Arf申し訳ありません。コードの別の部分に問題があります。よく働く! –