Функция шаблона перегрузки для перечислений generi c и других типов - PullRequest
2 голосов
/ 15 января 2020

У меня есть общая функция c, которая работает с любым типом перечисления. Я хотел бы перегрузить его пользовательскими классами, а также строкой и целым числом. Но я получу сообщение об ошибке перегрузки функции. Как я могу это исправить?

ошибка: вызов перегруженного 'show_value (MyAlpha)' является неоднозначным

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;
}

Ответы [ 2 ]

3 голосов
/ 15 января 2020

Вы должны сделать перегрузки SFINAE взаимоисключающими . В противном случае для enum типов обе шаблонные перегрузки точно совпадают.

например

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" не относится к типу std::string, но const char[]. Так что измените show_value("Rainy day"); на show_value(std::string("Rainy day"));.

0 голосов
/ 15 января 2020
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
void show_value(T x)

не более специализирован, чем (поймать все)

template<class T> void show_value(T x);

, поэтому вызов с enum неоднозначен.

Вы должны либо отказаться от универсального c один для non enum:

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

или предоставление им приоритета.

struct low_priority_overload {};
struct high_priority_overload : low_priority_overload{};
// Or use template <std::size_t N> struct priority_overload : priority_overload<N - 1>{}

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

void show_value_impl(high_priority_overload, int x) { cout<<"Int: "<<x<<endl; };

void show_value_impl(high_priority_overload, string x) { cout<<"String: "<<x<<endl; };

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


template<class T>
void show_value(T x)
{
   show_value_impl(high_priority_overload{}, x);
}

...