0

I have encountered a problem while dealing with template specialization. I'd like to have method that has an enum as argument and depending on it call specialized templated method. Heres the presentation:

#include <iostream>

enum EnumType
{
    ENUM1,
    ENUM2,
    ENUM3
};

class Test
{
public:
    template <EnumType enumType>
    bool enumFunc(const int i )
    {
        std::cout << i << " default\n";
        return false;
    }

    bool func(const EnumType e);
};

template<>
bool Test::enumFunc<ENUM2>(const int i )
{
    std::cout << i << " ENUM2 \n";
    return true;
}
//... and other specializations

bool Test::func(const EnumType e)
{
    // this one works
    // return enumFunc<ENUM2>(3);

    // but this:
    // error: no matching function for call to 'Test::enumFunc<e>(int)
    return enumFunc<e>(3);
}

int main()
{
    Test a;
    a.enumFunc<ENUM2>(2); // works

    a.func(ENUM2); // doesnt even get there due to previous error

    return 0;
}
Piodo
  • 616
  • 4
  • 20
  • Please edit the question to include the problem you're having. – Spencer Dec 29 '19 at 00:47
  • 4
    In `func`, you'd need a switch statement with a case for each enum value, calling a corresponding specialization. `e` is only known at runtime, but a template argument must be known at compile time. – Igor Tandetnik Dec 29 '19 at 00:50
  • @IgorTandetnik This works. I also tried with constexpr switch function. Seems like it is also working - can it be workaround for compile-time method with enum argument or I am wrong? – Piodo Dec 29 '19 at 09:42

1 Answers1

2

As noted in the comments, the value of the argument e is only known at run time, so you cannot use template specializations (which are evaluated at compile time). The following is, perhaps, the simplest implementation of your Test::func():

bool Test::func(const EnumType e)
{
    switch (e) {
        case ENUM1: return enumFunc<ENUM1>(3);
        case ENUM2: return enumFunc<ENUM2>(3);
        case ENUM3: return enumFunc<ENUM3>(3);
    }
    return false; // Handle error condition(s)
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
  • This works. I also tried with constexpr switch function. Seems like its working - can it be workaround for compile-time method with enum argument or I am wrong? – Piodo Dec 29 '19 at 09:33
  • I'm not sure what you mean by `constexpr switch` - but there will be *many* limitations on what your 'ultimately-called' specialization functions can do if they are restricted to "constexpr" return values. Also, this discussion may be helpful: [Switch in constexpr function](https://stackoverflow.com/questions/45534410/switch-in-constexpr-function). – Adrian Mole Dec 29 '19 at 09:43
  • @Piodo You can certainly add `constexpr` to the definition of `Test::func` but then you can only *actually* use it in other `constexpr` exressions if: (1) Each specialization of `enumFunc` is also declared `constexpr`; (2) the argument given to the `func` call *must also* be a `const` - as it is in your `a.func(ENUM2);` statement. – Adrian Mole Dec 29 '19 at 10:08