我们说我有几种类型绑定到变体中。 另一方面,我有一个枚举,其中可以推导出一些以前的类型,所以我可以有一个运行时伪工厂:
#include <boost/variant.hpp>
enum class Type { W, X, Y, Z };
struct A {};
struct B
{
B(int) {}
};
struct C
{
C(int, int) {}
};
using variant_t = boost::variant<A, B, C>;
template<typename... Args>
variant_t MakeVariantOverEnum(Type type, Args&&... args)
{
switch (type)
{
case Type::X: return B(std::forward<Args>(args)...); break;
case Type::Z: return C(std::forward<Args>(args)...); break;
default: return A(std::forward<Args>(args)...); break;
}
}
// meant to be fully runtime
const Type GetTypeFromIO() { return Type::Z; }
const int GetFirstArgFromIO() { return 0; }
const int GetSecondArgFromIO() { return 0; }
int main()
{
const Type type = GetTypeFromIO();
const int firstArg = GetFirstArgFromIO();
const int secondArg = GetSecondArgFromIO();
variant_t newVariant;
if (firstArg != 0 && secondArg != 0) newVariant = MakeVariantOverEnum(type, firstArg, secondArg);
else if (firstArg != 0) newVariant = MakeVariantOverEnum(type, firstArg);
else newVariant = MakeVariantOverEnum(type);
}
在这段代码中,有两件事让我很烦恼:
**如何通过传递所有参数,然后丢弃那些无效的&#39;来对MakeVariantOverEnum进行1次调用?案例(我的样本中= = 0)?我可以使用一些SFINAE机制在MakeVariantOverEnum中进行吗?
**它没有编译,因为编译器试图将所有构造函数与所有参数匹配:
main.cpp: In instantiation of 'variant_t MakeVariantOverEnum(Type, Args&& ...) [with Args = {const int&, const int&}; variant_t = boost::variant<A, B, C>]':
main.cpp:44:100: required from here
main.cpp:24:59: error: no matching function for call to 'B::B(const int&, const int&)'
case Type::X: return B(std::forward<Args>(args)...); break;
^
main.cpp:24:59: note: candidates are:
main.cpp:9:2: note: B::B(int)
B(int) {}
^
main.cpp:9:2: note: candidate expects 1 argument, 2 provided
main.cpp:7:8: note: constexpr B::B(const B&)
struct B
^
main.cpp:7:8: note: candidate expects 1 argument, 2 provided
main.cpp:7:8: note: constexpr B::B(B&&)
main.cpp:7:8: note: candidate expects 1 argument, 2 provided
等等其他类型...
所以我的问题是:我怎么能让它在这一点上起作用?
谢谢!
PS:代码在这里生效=&gt; http://coliru.stacked-crooked.com/a/4bc1e326be27b3dd
答案 0 :(得分:0)
解决问题的最简单方法:
enum class Type { W, X, Y, Z };
struct A {};
struct B
{
B(int) {}
};
struct C
{
C(int, int) {}
};
using variant_t = boost::variant<A, B, C>;
variant_t MakeVariantOverEnum(Type type, int param1, int param2)
{
switch (type)
{
case Type::X: return B(param1);
case Type::Z: return C(param1, param2);
default: return A();
}
}
// meant to be fully runtime
const Type GetTypeFromIO() { return Type::Z; }
const int GetFirstArgFromIO() { return 0; }
const int GetSecondArgFromIO() { return 0; }
int main()
{
const Type type = GetTypeFromIO();
const int firstArg = GetFirstArgFromIO();
const int secondArg = GetSecondArgFromIO();
variant_t newVariant = MakeVariantOverEnum(type, firstArg, secondArg);
}
可变参数模板只会让事情变得更复杂,无论如何都无法帮助你。
如果所有结构使用相同的参数(至少:如果使用该参数,则在任何地方使用相同的类型),这将起作用。但是,如果您为不同的对象使用不同的参数类型,则需要考虑在主函数本身中进行切换是否更容易(然后获取正确的参数):
假设以下扩展:
struct D
{
D(float) {}
}
所以现在你突然有一种情况,你的const int firstArg
将是一个浮动......(然而这对于B和C不起作用)
或者,您可以指定第三个参数float param3
,并在创建类型时仅使用此参数。 (但那么param1和param2呢?)
注意:仍然可以使用一些工厂模式,但这会更复杂(每个对象都需要自己的工厂,它将获得正确的参数,然后创建正确的结构......)