Например, я хочу реализовать свою собственную универсальную функцию сортировки, я хочу, чтобы тип, который будет передан, был Indexable
и элемент внутри будет Comparable
template <typename Cont>
**type_check: Cont is Indexable, Cont::Element is Comparable**
void my_sort(Cont& cont){
// do sorting work
}
Когда я делаю my_sort(vector<int>{1,6,5,4})
было бы хорошо
Но когда my_sort(linkedlist<int>{1,6,5,4})
потерпел бы неудачу во время компиляции / выполнения, потому что linkedlist
не является Indexable
,
Так есть ли способ сделать такого рода программирование контракта типа?
Постскриптум Я нахожусь в среде C ++ 11, но также приветствуется любое решение в более поздней версии C ++
С SFINAE вы можете сделать что-то вроде:
template <typename Cont>
auto my_sort(Cont& cont)
-> decltype(cont[42], // Indexable
void(), // That void to avoid evil overload of operator comma
std::declval<Cont::Element>() < std::declval<Cont::Element>(), // Comparable
void()) // That final void for the return type of sort
{
// do sorting work
}
std::enable_if
является альтернативой ( decltype
) если у вас есть готовые черты.
Как уже упоминалось в комментариях, как только Концепции ТС пробившись в стандарт C ++, вы сможете сделать это с помощью чего-то вроде:
template <typename T>
concept Sortable = requires(T t) {
{ t[0] < t[0] } -> bool
};
template <Sortable Cont>
my_sort(Cont& cont) {
// do sorting work
}
Старая версия Concepts TS реализована в GCC с флагом -fconcepts, но не будет в стандарте до C ++ 20. До тех пор, вы можете обойтись с трюками SFINAE:
template <typename Cont>
std::enable_if_t<std::is_convertible_v<decltype(std::declval<Cont>()[0] < std::declval<Cont>()[0]), bool>>
my_sort(Cont& cont) {
// ...
}
Это не удастся скомпилировать, если для данного Cont c
, c[0] < c[0]
либо недействителен, либо не конвертируется в bool
,
Live Demo