Home > Software engineering >  How to define the different template structs with different enums
How to define the different template structs with different enums

Time:05-24

I've two enums as below:

enum TTT {t = 2};

enum XXX {x = 2};

I'm trying to make some struct to help me get the name of an enum. Here is what I've done:

template<TTT>
struct StrMyEnum {
    static char const* name() { return "unknown"; }
};

template<>
struct StrMyEnum<t> {
    static char const* name() { return "tt"; }
};

It works. Now I can get the name of the enum t: StrMyEnum<t>::name().

However, if I write another group of template structs for XXX, it doesn't seem to work.

template<XXX>
struct StrMyEnum {
    static char const* name() { return "unknown"; }
};

template<>
struct StrMyEnum<x> {
    static char const* name() { return "xx"; }
};

Now I get a compile error: could not convert 'x' from 'XXX' to 'TTT'. It seems that the compiler is trying to match the StrMyEnum<x> with TTT...

I don't know why.

So template can't distinguish the different enums? Is it possible to write some structs for different enums?

CodePudding user response:

You can use C 17 Non-type template parameter and make a partial specialization for t and x, since they are actually different types

enum TTT { t = 2 };

enum XXX { x = 2 };

template<auto>
struct StrMyEnum {
  static char const* name() { return "unknown"; }
};

template<>
struct StrMyEnum<t> {
  static char const* name() { return "tt"; }
};

template<>
struct StrMyEnum<x> {
  static char const* name() { return "xx"; }
};

Demo

CodePudding user response:

StrMyEnum identifies the name of the template.
You can have a general declaration for it, and then some specializations.
But you cannot have a second set of declaration specializations (like you did with the set for XXX).

What you can do is have one template parametrized with both the enum type and the enum value. Then you can have 2 levels of specializations:

  1. For a specific value of a specific enum.
  2. Default for a specific enum.

See the code below:

#include <iostream>

enum TTT { t = 2, t2 = 3 };
enum XXX { x = 2, x2 = 3 };

template <typename T, T val>
struct StrMyEnum {
    static char const* name() { return "unknown"; }
};

// Default specialization for TTT:
template <TTT t>
struct StrMyEnum<TTT, t> {
    static char const* name() { return "TTT"; }
};

// Specialization for TTT::t:
template <>
struct StrMyEnum<TTT, t> {
    static char const* name() { return "TTT::t"; }
};

// Specialization for XXX::x:
template <>
struct StrMyEnum<XXX, x> {
    static char const* name() { return "XXX::x"; }
};

int main()
{
    std::cout << StrMyEnum<TTT, t2>().name() << std::endl;
    std::cout << StrMyEnum<TTT, t>().name() << std::endl;
    std::cout << StrMyEnum<XXX, x2>().name() << std::endl;
    std::cout << StrMyEnum<XXX, x>().name() << std::endl;
    return 0;
}

Output:

TTT
TTT::t
unknown
XXX::x

Demo: https://godbolt.org/z/zW547T9nf.

  • Related