I have code such as the following, that maps template types to an enumerated value. However, the value MyEnum::C
is only defined when the code utilizes the template something<double>
. Is there a way to change the template declaration/definition such that the following compiles?
E.g., I thought if I added a default template parameter to the end of the declaration of the something
template, that would be sufficient to make the full specializations only partial specializations, which would only compile the specializations when used. However, I couldn't figure out the correct syntax to do so.
#include <iostream>
using namespace std;
enum class MyEnum
{
A,
B
};
template<typename T>
struct something;
template<>
struct something<int>
{
static constexpr auto value = MyEnum::A;
};
template<>
struct something<double>
{
static constexpr auto value = MyEnum::C;
};
int main()
{
cout << static_cast<int>(something<int>::value) << endl;
return 0;
}
I thought the following would work, but didn't:
template<typename T>
constexpr MyEnum toEnum()
{
if constexpr (std::is_same_v<int, T>)
return MyEnum::A;
else if constexpr (std::is_same_v<double, T>)
return MyEnum::C;
}
Even if you changed the full specialization something<double>
into a partial specialization depending on some other template parameter T
, you still cannot use MyEnum::C
inside that specialization and expect your program to be well-formed, because MyEnum::C
is a non-dependent construct, and compilers may reject templates containing invalid non-dependent constructs, even if those templates are never instantiated.
For the same reason, sticking MyEnum::C
into a discarded if constexpr
branch does not make the program valid.
However, you can do something like this:
template<typename T, typename E = MyEnum>
struct something;
template<>
struct something<int>
{
static constexpr auto value = MyEnum::A;
};
template<typename E>
struct something<double, E>
{
static constexpr auto value = E::C;
};
Now, you're no longer directly mentioning MyEnum::C
; the dependent construct E::C
may or may not be valid, depending on whether E
actually ends up being MyEnum
.
Whether this strategy is suitable for your particular use case, I have no idea.