Ограничение типов шаблонов классов - PullRequest
4 голосов
/ 23 мая 2019

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

Я уверен, что где-то уже есть ответ на этот вопрос, но я не смог его найти.

Вот два способа, которые я нашел для решения проблемы:

Первый (SFINAE):

template <typename T, typename = typename std::enable_if<std::is_same<T, int>::value>::type>
class Integer {
public:
    T value;
};

int main() {
    Integer<int> i;             // Alowed
    Integer<double> d;          // Not allowed
    Integer<double, double> dd; // Allowed (Undesired)

    return 0;
}

Что мне не нравится в этом решении, так это то, что третий пример в основной функцииработает.

Секунда (static_assert):

#include <type_traits>

template <typename T>
class Integer {
    static_assert(std::is_same<T, int>::value, "T must be int");
public:
    T value;
};

int main() {
    Integer<int> i;    // Allowed
    Integer<double> d; // Not allowed

    return 0;
}

Я думаю, что это решение хорошо, но мне было интересно, есть ли более элегантный или SFINAE способ сделать то же самое.

В этом случае я хотел бы иметь возможность принудительно установить, что тип шаблона T должен быть целочисленным для этого простого примера.Конечно, в этом случае класс даже не должен быть шаблоном, и я мог бы просто объявить тип внутри класса Integer типа int, но я хочу использовать то, что я изучаю здесь, в более сложной ситуации.

Ответы [ 2 ]

4 голосов
/ 23 мая 2019

Вы можете исправить первый пример, используя неназванный параметр шаблона нетипичного типа. Меняя его на

template <typename T, std::enable_if_t<std::is_same_v<T, int>, bool> = true>
class Integer {
public:
    T value;
};

позволит только Integer<int> i; скомпилировать. Это также мешает пользователям пытаться обойти это, используя Integer<double, true> dd;

2 голосов
/ 23 мая 2019

Используйте SFINAE другим (правильным) способом:

template <typename T, typename std::enable_if<std::is_same<T, int>::value, int>::type = 0>
class Integer {
public:
    T value;
};

Не более угон.

...