Сценарий:
У меня есть множество типов, которые можно классифицировать как контейнеры последовательностей.
Все контейнеры последовательностей представляют собой структуры данных, но не каждая структура данных будет контейнером последовательности.Как использовать SFINAE для выбора ближайшего типа соответствия типа?
Вот пример иллюстрированного в коде. В этом примере единственным «важным типом» является Array_T. Он подразделяется на две категории: это контейнер последовательности, и поскольку все контейнеры последовательностей представляют собой структуры данных, это, в свою очередь, структура данных.
//A sequence container type
class Array_T{};
//A type trait for that particular sequence container
template <typename T> struct Is_Array { static const bool value = false; };
template <> struct Is_Array<Array_T> { static const bool value = true; };
//A type trait to identify all of the sequence containers
template <typename T> struct Is_A_Sequence_Container { static const bool value = Is_Array<T>::value
/* would probably "or" together more sequence types, but we only have Array_T in this example */;};
//A type trait to identify all of the data structures
template <typename T> struct Is_A_Data_Structure { static const bool value = Is_A_Sequence_Container<T>::value
/* would probably "or" together more data structure types, but we only have sequence containers in this example */;};
Обратите внимание, что на Array_T не может быть выполнено наследование; он должен оставаться таким, каким он был объявлен.
Проблема:
Я хочу написать две функции. Одна функция будет обрабатывать все контейнеры последовательностей, а другая функция будет обрабатывать все структуры данных. Я не знаю, будет ли фактически существовать функция контейнера последовательности или нет, поскольку эта часть кода может или не может быть сгенерирована.
Итак, как я могу использовать мета-шаблонное программирование, чтобы выбрать наиболее подходящую идентификацию для типа? Вот два примера ожидаемого поведения:
Случай 1:
// ...
//Both functions exist! Call the more specific one.
// ...
function(Array_T{}); // prints "sequence container"
Случай 2:
// ...
//Only the data structure one exists(not the sequence container one)
// ...
function(Array_T{}); // prints "data structure"
Моя попытка до сих пор:
#include <iostream>
#include <type_traits>
//A sequence container type
class Array_T{};
//A type trait for that particular sequence container
template <typename T> struct Is_Array { static const bool value = false; };
template <> struct Is_Array<Array_T> { static const bool value = true; };
//A type trait to identify all of the sequence containers
template <typename T> struct Is_A_Sequence_Container { static const bool value = Is_Array<T>::value
/* would probably "or" together more sequence types, but we only have Array_T in this example */;};
//A type trait to identify all of the data structures
template <typename T> struct Is_A_Data_Structure { static const bool value = Is_A_Sequence_Container<T>::value
/* would probably "or" together more data structure types, but we only have sequence containers in this example */;};
// ↑ all of this code was already shown to you
//NOTE: This function MAY OR MAY NOT actually appear in the source code
//This function handles all sequence types
template<class T, typename std::enable_if<Is_A_Sequence_Container<T>::value,int>::type=0>
void function(T t) {
std::cout << "sequence container" << std::endl;
return;
}
//This function handles all data structures; assuming a more specific function does not exist(*cough* the one above it)
template<class T, typename std::enable_if<Is_A_Data_Structure<T>::value,int>::type=0>
void function(T t) {
std::cout << "data structure" << std::endl;
return;
}
int main(){
function(Array_T{});
}
Теперь Я понимаю, что это не работает, потому что значение будет истинно для ОБОИХ из enable_ifs.
Поэтому я хочу добавить вторую функцию enable_if в функцию структуры данных, чтобы проверить, существует ли функция контейнера последовательности. Что-то вроде этого:
//...
//This function handles all data structures; assuming a more specific function does not exist(*cough* the one above it)
template<class T, typename std::enable_if<Is_A_Data_Structure<T>::value,int>::type=0,
typename std::enable_if</*if the more specific function does not exist*/,int>::type=0>>
void function(T t) {
std::cout << "data structure" << std::endl;
return;
}
int main(){
function(Array_T{});
}
И вот где я застрял. Есть ли способ сделать это, не касаясь замедления Array_T, и без привлечения третьей функции для диспетчеризации?
Я думаю, что C++ 14 понятий lite решит вам проблему – Manu343726