我知道,有几个主题,要求非常接近的事情,但我不能让它在我的情况下工作。
我想在运行时期间构建一个具有索引访问权限的模板化工厂。因此我有几种类型相同的基类型。工厂获取每个模板参数能够获取的类型。对工厂的调用只给出一个索引。这是一个小例子:
#include <iostream>
#include <memory>
#include <tuple>
struct Base {
};
struct A : Base {
A(int) { std::cout << "A" << std::endl; }
};
struct B : Base {
B(int) { std::cout << "B" << std::endl; }
};
struct C : Base {
C(int) { std::cout << "C" << std::endl; }
};
template <typename ... Types>
struct Factory {
typedef std::tuple<Types...> TypesTuple;
std::shared_ptr<Base> operator ()(int index) {
return produce(index);
}
std::shared_ptr<Base> produce(int index) {
switch (index) {
case 0: return std::make_shared<typename std::tuple_element<0, TypesTuple>::type>(42);
case 1: return std::make_shared<typename std::tuple_element<1, TypesTuple>::type>(42);
}
throw;
}
};
//==============================================================================
int main() {
Factory<A, C> factory_ac;
auto a1 = factory_ac(0);
auto c1 = factory_ac(1);
Factory<A, B, C> factory_bc;
auto a2 = factory_bc(0);
auto b2 = factory_bc(1);
auto c2 = factory_bc(2);
}
我尝试用
重载了crop方法template <typename = typename std::enable_if<std::tuple_size<TypesTuple>::value==2>::type>
计算大小并提供相应的switch
语句,但这不会编译,不允许超载。
我尝试使用https://stackoverflow.com/a/7383493/2524462但我无法使其工作,因为参数包不会扩展为lambda并将其包装在模板函数中我遇到了constexpr
数组的问题因为我没有琐碎的类型。
Boost MPL for_each
浮现在脑海中,但我遇到了编译问题,因为我的类型不是简单的构造。
那么如何更改工厂以使主要编译和工作?
答案 0 :(得分:4)
这似乎可以很直接地完成:
template <typename T>
std::shared_ptr<Base> make() {
return std::make_shared<T>();
}
template <typename... T>
class Factory {
public:
std::shared_ptr<Base> operator()(int index) {
static constexpr std::shared_ptr<Base> (*factories[])() = {
&make<T>...
};
if (index < 0 && sizeof...(T) <= index) {
throw std::range_error("type index out of range");
}
return (factories[index])();
}
};
我目前无法编译代码,但是这一行应该有效:想法是创建一个工厂函数数组,然后调用这个数组。
答案 1 :(得分:1)
如果我已正确理解您的要求,我认为这样做符合您的要求:
template<int... Is>
struct indices { typedef indices type; };
template<int N, int... Is>
struct make_indices : make_indices<N - 1, N - 1, Is...> { };
template<int... Is>
struct make_indices<0, Is...> : indices<Is...> { };
template<typename... Types>
struct Factory
{
typedef std::tuple<Types...> TypesTuple;
std::shared_ptr<Base> operator()(int const index)
{
return produce(index);
}
std::shared_ptr<Base> produce(int const index)
{
return produce_impl(make_indices<sizeof...(Types)>(), index);
}
template<int I, int... Is>
std::shared_ptr<Base> produce_impl(indices<I, Is...>, int const index)
{
if (I == index) {
return std::make_shared<typename std::tuple_element<I, TypesTuple>::type>(42);
}
return produce_impl(indices<Is...>(), index);
}
std::shared_ptr<Base> produce_impl(indices<>, int const index)
{
throw "Uh-oh!";
}
};
请参阅输出here。