Search code examples
c++c++11templatessfinae

Overload template function for generic enum and the other types


I have a generic function which works on any type of enum. I would like to overload it with custom defined classes as well as string and integer. But, I will receive a function overload error message. How can I fix that?

error: call of overloaded 'show_value(MyAlpha)' is ambiguous

wandbox

#include <type_traits>
#include <iostream>
#include <string>

using namespace std;

enum MyAlpha
{
   ALPHA,
   BETA
};

enum Animal
{
    ELEFANT,
    GOAT,
    RABIT
};

class MyClass
{
public:
    string text;
    MyClass(string text): text(text) {} 
};

template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };

void show_value(int x) { cout<<"Int: "<<x<<endl; };

void show_value(string x) { cout<<"String: "<<x<<endl; };

template<class T>
void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };


int main()
{
    show_value(MyAlpha(BETA));
    show_value(Animal(RABIT));
    show_value(5);
    show_value("Rainy day");
    show_value(MyClass("Waterfall"));
    return 0;
}


Solution

  • You should make the overloads of SFINAE mutually exclusive. Otherwise for enum types both the templated overloads are exact match.

    e.g.

    template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
    void show_value(T x) { cout<<"Enum: "<<(int)x<<endl; };
    
    template<class T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
    void show_value(T x) { cout<<"Obj.text: "<<x.text<<endl; };
    

    LIVE


    PS: "Rainy day" is not of type std::string but const char[]. So change show_value("Rainy day"); to show_value(std::string("Rainy day"));.