#include<memory>
#include<iostream>
#include<type_traits>
using namespace std;
template<typename T, typename... types>
struct T_fabric
{
enum {size = sizeof...(types)};
T_fabric<types...> fabric;
template < size_t N,
class Tc = typename enable_if<size == N, T>::type>
shared_ptr<Tc> create() { return make_shared<Tc>(); }
template < size_t N,
class Tc = typename enable_if<size != N, T>::type>
auto create() -> decltype(fabric.create<N>()) { return fabric.create<N>(); }
};
template<typename T>
struct T_fabric<T> {
template < size_t N,
class = typename enable_if<0 == N>::type>
shared_ptr<T> create() { return make_shared<T>(); }
};
int main() {
T_fabric<double, float, int> fabric;
auto v0 = *(fabric.create<0>());
auto v1 = *(fabric.create<1>());
auto v2 = *(fabric.create<2>());
std::cout << "v0: " << typeid(v0).name() << '\n';
std::cout << "v1: " << typeid(v1).name() << '\n';
std::cout << "v2: " << typeid(v2).name() << '\n';
return 0;
}
I2luY2x1ZGU8bWVtb3J5PgojaW5jbHVkZTxpb3N0cmVhbT4KI2luY2x1ZGU8dHlwZV90cmFpdHM+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgoKCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lLi4uIHR5cGVzPgpzdHJ1Y3QgVF9mYWJyaWMKewogICAgZW51bSB7c2l6ZSA9IHNpemVvZi4uLih0eXBlcyl9OwogICAgVF9mYWJyaWM8dHlwZXMuLi4+IGZhYnJpYzsKCiAgICB0ZW1wbGF0ZSA8IHNpemVfdCBOLAogICAgICAgICAgICAgICBjbGFzcyBUYyA9IHR5cGVuYW1lIGVuYWJsZV9pZjxzaXplID09IE4sIFQ+Ojp0eXBlPgogICAgc2hhcmVkX3B0cjxUYz4gY3JlYXRlKCkgeyByZXR1cm4gbWFrZV9zaGFyZWQ8VGM+KCk7IH0KICAgIAogICAgdGVtcGxhdGUgPCBzaXplX3QgTiwKICAgICAgICAgICAgICAgY2xhc3MgVGMgPSB0eXBlbmFtZSBlbmFibGVfaWY8c2l6ZSAhPSBOLCBUPjo6dHlwZT4KICAgIGF1dG8gY3JlYXRlKCkgLT4gZGVjbHR5cGUoZmFicmljLmNyZWF0ZTxOPigpKSB7IHJldHVybiBmYWJyaWMuY3JlYXRlPE4+KCk7IH0gICAgCn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpzdHJ1Y3QgVF9mYWJyaWM8VD4gewogICAgdGVtcGxhdGUgPCBzaXplX3QgTiwKICAgICAgICAgICBjbGFzcyA9IHR5cGVuYW1lIGVuYWJsZV9pZjwwID09IE4+Ojp0eXBlPgogICAgc2hhcmVkX3B0cjxUPiBjcmVhdGUoKSB7IHJldHVybiBtYWtlX3NoYXJlZDxUPigpOyB9Cn07CgoKaW50IG1haW4oKSB7CiAgICBUX2ZhYnJpYzxkb3VibGUsIGZsb2F0LCBpbnQ+IGZhYnJpYzsKICAgIAogICAgYXV0byB2MCA9ICooZmFicmljLmNyZWF0ZTwwPigpKTsKICAgIGF1dG8gdjEgPSAqKGZhYnJpYy5jcmVhdGU8MT4oKSk7CiAgICBhdXRvIHYyID0gKihmYWJyaWMuY3JlYXRlPDI+KCkpOwogICAgCiAgICBzdGQ6OmNvdXQgPDwgInYwOiAiIDw8IHR5cGVpZCh2MCkubmFtZSgpIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgInYxOiAiIDw8IHR5cGVpZCh2MSkubmFtZSgpIDw8ICdcbic7CiAgICBzdGQ6OmNvdXQgPDwgInYyOiAiIDw8IHR5cGVpZCh2MikubmFtZSgpIDw8ICdcbic7CgogICAgCiAgICByZXR1cm4gMDsKfQ==