шаблоны — параметры ограниченного типа в C ++, есть ли причина его отсутствия?

Java и я думаю, C # (и другие) поддержка Параметры ограниченного типа что позволяет нам ограничивать типы, которые могут использоваться в шаблонных классах / функциях.

Мне любопытно, если есть причина, официальная или нет, не добавлять родные поддержка ограниченных типов в C ++? Какое-то отношение к тому, как шаблоны в настоящее время обрабатываются? Многочисленные проблемы наследования?

Я ожидаю, что это будет весьма полезно.

2

Решение

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

Кроме того, общие ограничения, на которые вы ссылаетесь, не являются ограниченными типами совсем. Единственное ограничение, которое они поддерживают, это «X наследует от Y», по сути, и, честно говоря, SFINAE с std::is_base_of покрывает эту ситуацию просто отлично. C ++ потребует чего-то гораздо более мощного, чтобы быть полезным, поскольку наследование во время выполнения является одной из наименее полезных функций.

1

Другие решения

В C ++ есть SFINAE, который довольно легко можно использовать через std :: enable_if. В сочетании с type_traits это, на самом деле, IMO, более мощный, чем ограниченные типы, которые есть в Java и C #. Немного поработав, вы также можете сделать несколько хороших функций constexpr, чтобы проверить эти вещи для вас. Добавьте к этому несколько макросов, и у вас получится что-то похожее на это

#include <iostream>
#include <type_traits>

#define ENABLE_IF typename std::enable_if<
#define THEN(T) ,T>::type

class foo {};
class bar : public foo {};

template<class T, class U>
constexpr bool extends() {
return std::is_base_of<
typename std::remove_reference<U>::type,
typename std::remove_reference<T>::type
>::value;
}

template<class T>
ENABLE_IF extends<T, foo>() THEN(void) test(T&& v) {
std::cout << "T extends foo!!";
}

int main() {
test(bar{});
}

Сейчас я не уверен, что возобновил бы это, но это выполнимо, и на данный момент я не вижу никаких проблем в этом, кроме того, что SFINAE трудно отлаживать

1

В большинстве случаев ограничения на аргумент шаблона должны не быть на типе, но на операциях, в которых нуждается шаблон. C ++ делает это несколько неловко, просто потому, что вы получаете сообщение об ошибке, если там нет операции, которую использует шаблон. Например:

template <class T>
void show(T t) {
std::cout << t << std::endl;
}

Если вы вызываете эту функцию шаблона с типом, который не реализует operator<< вы получите ошибку. Подход Java должен был бы определить интерфейс с print метод, и требуют, чтобы пользователь передал объект типа, который реализует этот интерфейс. Подход C ++ не требует всего этого механизма.

Проблема с этим в C ++ состоит в том, что вы можете получить сообщения об ошибках, которые очень запутаны. Часто отсутствующая операция используется в некоторой низкоуровневой части другого шаблона, и сообщение об ошибке не имеет четкого отношения к написанному вами коду. Это один из факторов, лежащих в основе концепций: автор шаблона может указать, какие операции он использует, и передача объекта, тип которого не поддерживает эти операции, приведет к нарушению концепции прямо на интерфейсе, а не глубоко внутри. реализации, так что вы, вероятно, получите более полезное сообщение об ошибке.

0
По вопросам рекламы [email protected]