Сценарий:
У меня есть множество типов, которые можно классифицировать как контейнеры последовательностей.
Все контейнеры последовательностей представляют собой структуры данных, но не каждая структура данных будет контейнером последовательности.
Вот пример того, что показано в коде. В этом примере единственным "важным типом" является 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 и без привлечения третьей функции для отправки?