场景:
我有多种类型可以归类为序列容器。
所有序列容器都是数据结构,但并非每个数据结构都是序列容器。
这是代码中说明的示例。此示例中涉及的唯一“重要类型”是 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"
案例二:
// ...
//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 的两个值都是 true。
所以我想在数据结构函数中添加第二个 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 减速且不涉及第三个调度函数的情况下做到这一点?