Suppose I have a class C
that has holds a std::variant<A, B>
. The constructor of C
must be a templated constructor that can accept any type, and based on that type it must initialize the variant in different ways.
Here is a simplified overview:
struct A {
// ...
};
struct B {
// ...
};
class C {
public:
template <typename T>
C(T arg) {
if constexpr (std::same_v<B, T>) {
var = B{arg};
}
else if constexpr (std::is_constructible<A, T>) {
var = A{arg};
}
}
private:
std::variant<A, B> var;
};
I am looking for a way to squash these if constexpr statements by using some template metaprogramming magic, so I may rewrite the constructor like this (hoping to avoid the extra initialization of the variant):
template<T>
struct DeduceAOrB {
// ..... somehow check the conditions here
};
template <typename T>
C(T arg)
: var(DeduceAOrB<T>::type{arg})
{}
Important note is that the variant may need to be expanded in the future, so the solution must be viable for arbitrarily many types
One way is to create a helper function containing the conditions and use it in initializer list as shown below:
class C {
private:
//helper function checking for different conditions and returning based on result
template<typename T>
static constexpr auto helperFunc(T arg)
{
if constexpr (std::is_same_v<B, T>) {
return B{arg};
}
else if constexpr (std::is_constructible_v<A, T>) {
return A{arg};
} else {
return A{};
}
}
public:
template <typename T>
//----------------VVV------------------>use helperFunc initializer list
C(T arg): var(helperFunc(arg)){
}
private:
std::variant<A, B> var;
};