テンプレートについて質問があり、それはコードにあります:
template<typename T>
struct foo {
T t;
};
template<typename FooType>
struct bar {
T t; //<- how to get T here (preferably without using typedef in foo)
};
以下は、一般的なテンプレート引数型エクストラクタです。
#include <tuple>
template <typename> struct tuplify;
template <template <typename...> class Tpl, typename ...Args>
struct tuplify<Tpl<Args...>>
{
using type = std::tuple<Args...>;
};
template <typename T, unsigned int N>
using get_template_argument
= typename std::tuple_element<N, typename tuplify<T>::type>::type;
使用法:
get_template_argument<std::vector<int>, 1> a; // is a std::allocator<int>
またはあなたの場合:
get_template_argument<FooType, 0> t;
あなたの質問を正しく理解していれば、次のようにテンプレートの特殊化を使用できます。foo<>
クラス テンプレートが与えられた場合:
template<typename T>
struct foo {
T t;
};
bar<>
プライマリ テンプレートと対応する特殊化を次のように定義します。
template<typename FooType>
struct bar;
template<typename T>
struct bar<foo<T>> {
T t; // T will be int if the template argument is foo<int>
};
bar
型引数として のインスタンスを提供することによって常にインスタンス化することになっているという前提の下でfoo<>
、プライマリ テンプレートを未定義のままにしておくことができます。
特殊化はfoo<T>
パターンに一致するため、foo<>
でインスタンス化された型が得られますT
。
簡単なプログラムでこのアプローチの有効性をテストする方法を次に示します。
#include <type_traits>
int main()
{
bar<foo<int>> b;
// This will not fire, proving T was correctly deduced to be int
static_assert(std::is_same<decltype(b.t), int>::value, "!");
}
対応するライブの例を次に示します。
に typedef を追加したくない、または追加できない場合はfoo
、独立した「エクストラクタ」テンプレートを追加で作成できます。
template <typename T> struct ExtractT;
template <typename T> struct ExtractT<foo<T> > {
typedef T type;
};
そしてそれを次のように使用します
template<typename FooType>
struct bar {
typename ExtractT<FooType>::type t;
};
それをExtractT
さらに一歩進めて、foo
template <typename T> struct ExtractT;
template <template <typename> class C, typename T> struct ExtractT<C<T> > {
typedef T type;
};
BoostまたはC++ 11標準ライブラリから何かを再発明するまで、など.