Предположим, что у меня есть несколько типов, связанных с вариантом. С другой стороны, у меня есть перечисление, на котором некоторые из предыдущих типов могут быть выведены из, так что я могу иметь время выполнения псевдо завод:Тип конструкции над перечислением и переадресация разного количества аргументов
#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);
}
2 вещи беспокоить меня в этом коде:
* * Как я могу получить только 1 вызов MakeVariantOverEnum, передав все аргументы и затем отбросив эти «недопустимые» случаи (== 0 в моем примере)? Могу ли я сделать это внутри MakeVariantOverEnum с помощью некоторого механизма SFINAE?
** Это не компилируется, поскольку компилятор пытается сопоставить все конструкторы со всеми аргументами:
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: код будет здесь =>http://coliru.stacked-crooked.com/a/4bc1e326be27b3dd