Как я могу написать шаблон функции для всех типов с определенной чертой типа?

StackOverflow https://stackoverflow.com/questions/2537229

  •  22-09-2019
  •  | 
  •  

Вопрос

Рассмотрим следующий пример:

struct Scanner
{
    template <typename T>
    T get();
};

template <>
string Scanner::get()
{
    return string("string");
}

template <>
int Scanner::get()
{
    return 10;
}

int main()
{
    Scanner scanner;
    string s = scanner.get<string>();
    int i = scanner.get<int>();
}

В Scanner класс используется для извлечения токенов из некоторого источника.Приведенный выше код работает нормально, но терпит неудачу, когда я пытаюсь get другие интегральные типы, такие как char или unsigned int.Код для чтения этих типов точно такой же, как код для чтения int.Я мог бы просто дублировать код для всех других целых типов, которые я хотел бы прочитать, но я бы предпочел определить один шаблон функции для всех целых типов.

Я попробовал следующее:

struct Scanner
{
    template <typename T>
    typename enable_if<boost::is_integral<T>, T>::type get();
};

Это работает как заклинание, но я не уверен, как получить Scanner::get<string>() чтобы снова функционировать.Итак, как я могу написать код, чтобы я мог делать scanner.get<string>() и scanner.get<any integral type>() и есть ли единое определение для чтения всех целых типов?

Обновить:бонусный вопрос:Что, если я хочу принять более одного диапазона классов, основанных на некоторых чертах?Например:как мне следует подойти к этой проблеме, если я хочу иметь три get функции, которые принимают (i) целочисленные типы (ii) типы с плавающей запятой (iii) строки соответственно.

Это было полезно?

Решение

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }
    template <typename T>
    typename boost::disable_if<boost::is_integral<T>, std::string>::type get()
    {
        return "string";
    }
};

Обновление "Что, если я захочу принять более одного диапазона классов, основанных на некоторых чертах?"

struct Scanner
{
    template <typename T>
    typename boost::enable_if<boost::is_integral<T>, T>::type get()
    {
        return 10;
    }

    template <typename T>
    typename boost::enable_if<boost::is_floating_point<T>, T>::type get()
    {
        return 11.5;
    }

    template <typename T>
    std::string get(
          typename boost::disable_if<boost::is_floating_point<T>, T>::type* = 0, 
          typename boost::disable_if<boost::is_integral<T>, T>::type* = 0)

    {
        return std::string("string");
    }
};

Другие советы

Перенесите на другой шаблон.Вот общий шаблон для того, что вы хотите:

template <typename T, bool HasTrait = false>
struct scanner_impl;

template <typename T>
struct scanner_impl
{
    // Implement as though the trait is false
};

template <typename T>
struct scanner_impl<true>
{
    // Implement as though the trait is true
};

// This is the one the user uses
template <typename T>
struct scanner : scanner_impl<T, typename has_my_trait<T>::value>
{
};
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top