Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ Prevent Compilation of Full Template Specialization

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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;
}

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading