Templated functions with strongly typed enums

77 Views Asked by At

I have the following code which seems to work fine on GCC/Clang but with Windows either silently fails at runtime or fails to compile with a duplicate COMDAT error depending on the code.

The crux of the matter is that I have a template function GetSize() that is templated on two different strongly typed enums.
In this sample below, compiling with cl.exe 19.38 will result in a duplicate symbol error for GetSize.

I've seen in production code that this pattern will compile fine but at runtime the GetSizeYEnum::one() will be "incorrectly" called when GetSizeXEnum::b() is expected.

What does the spec say about this?

enum class XEnum
{
    a = 0,
    b = 1
};

enum class YEnum
{
    zero = 0,
    one = 1
};

template <YEnum T>
struct V;

template <>
struct V<YEnum::zero>
{
    char x[40];
};

template <>
struct V<YEnum::one>
{
    char x[50];
};

namespace Debug {
template <XEnum T>
inline constexpr size_t GetSize();

template <> inline constexpr size_t GetSize<XEnum::a>() { return 10; }
template <> inline constexpr size_t GetSize<XEnum::b>() { return 20; }

template <YEnum T>
inline constexpr size_t GetSize() { return sizeof(V<T>); }

}

struct Doer
{
    void Perform(size_t v);

    template <XEnum T>
    void Perform()
    {
        Perform(Debug::GetSize<T>());
    }

    template <YEnum T>
    void Perform()
    {
        Perform(Debug::GetSize<T>());
    }
};

void Doer::Perform(size_t v)
{
    //std::cout << v << std::endl;
    v = v + v;
}

int  main()
{
    // The following 4 static assertions do not fail.
    static_assert(Debug::GetSize<XEnum::a>() == 10);
    static_assert(Debug::GetSize<XEnum::b>() == 20);
    static_assert(Debug::GetSize<YEnum::zero>() == 40);
    static_assert(Debug::GetSize<YEnum::one>() == 50);

    Doer d;

    d.Perform<XEnum::a>();
    d.Perform<XEnum::b>();
    d.Perform<YEnum::zero>();
    d.Perform<YEnum::one>();

    return 0;
}

Thanks!

Expected templated function with same definition to work for multiple strongly typed enums types.

0

There are 0 best solutions below