だからここにこのようなことをする例があります。テンプレートをインスタンス化するためのタイプのリストを取得し、それらを使用してテンプレートをインスタンス化し、インスタンスをタプルに格納し、タイプベースのルックアップget
メソッドを提供します。
#include <type_traits>
#include <utility>
#include <tuple>
// Metaprogramming boilerplate:
template<typename... Ts> struct type_list {};
template<typename T, typename list, typename=void> struct index_in;
template<typename T, typename T0, typename... Ts>
struct index_in<T, type_list<T0, Ts...>, typename std::enable_if<std::is_same<T,T0>::value>::type>
{
enum { value = 0 };
};
template<typename T, typename T0, typename... Ts>
struct index_in<T, type_list<T0, Ts...>, typename std::enable_if<!std::is_same<T,T0>::value>::type>
{
enum { value = index_in<T, type_list<Ts...>>::value+1 };
};
// The tuple of instantiations of Factory:
template<template<typename>class Factory, typename... Ts>
struct PolytypeFactory {
std::tuple< Factory<Ts>... > data;
template<typename T>
Factory<T>& get() {
return std::get< index_in< T, type_list<Ts...> >::value >( data );
}
template<typename T>
Factory<T> const& get() const {
return std::get< index_in< T, type_list<Ts...> >::value >( data );
}
};
// a test factory, that creates an instance of T from the constant 100.5:
template<typename T> struct maker100_5 { T operator()() const { return T(100.5); } };
// test code, where I create 100.5 as an int, double and char, then print them:
#include <iostream>
int main() {
PolytypeFactory<maker100_5, int, double, char> factory;
std::cout << factory.get<int>()() << "," << factory.get<double>()() << "," << factory.get<char>()() << "\n";
}
PolytypeFactory
必要に応じて、のコンテンツの構築を延期することができます。これには、を使用して、へboost::optional
のポインタを格納し、のようなメソッドを介して誰かがバージョンFactory<Ts>
を渡せるようにするか、または非常に凝ってインプレース構築を行うことができます。new
get()