0

I am trying to create a templated class containing enum-string pairs and unable to make type deduction work. With a following code i have two problems:

namespace {
template<typename T, size_t S>
using EnumStringArray = std::array<std::pair<T, const char*>, S>;
}

template<typename T, size_t S>
class EnumToString {
public:
    constexpr EnumToString(const EnumStringArray<T, S>& array) :
            _array(array)
    {}
private:
    EnumStringArray<T, S> _array;
};

template<typename T, size_t S>
EnumToString(const EnumStringArray<T, S>&) -> EnumToString<T, S>;

enum MyEnum {
    One, 
    Two
};

constexpr EnumToString enumStrings = {{{    //<---- does not compile without explicit types
        {One, "One"},
        {Two, "Two"}
}}};
  1. Why compiler can't deduce parameters of EnumToString by himself within constructor?
  2. Why user deduction guide does not help?

2 Answers2

1

{..} has not type and cannot be deduced (except as std::initializer_list<T> or T(&)[N]).

so regular constructor, or deduction guide doesn't help with CTAD here.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

The reason, as has mentioned by @Jarod42, is that in C++ brace initializers do not have any types and cannot be deduced by the compiler in the context of templates. The reason of this has been summarized here.

To fix it, you can use an auto variable to deduce the type and then pass it to your template method.

auto x = {{One, "One"}, {Two, "Two"}};
// Now x has a type, you can pass it to a template function. 
TonySalimi
  • 8,257
  • 4
  • 33
  • 62