使用模板进行递归类型检查
Recursive type check using templates
我有几个类型检查模板:is_object
来自type_traits
,isSupportedContainer
通过以下方式实现:
template <class T>
struct isSupportedContainer
: public false_type {};
template <class T>
struct isSupportedContainer < list<T> >
: public true_type {};
/*other containers*/
我想进行递归检查isSupported
不仅应用于容器类型,还应用于包含的类型。当前实现:
// using std::__and_ and std::for from type_traits
template <class T>
struct isSupported
: public __and_ < __or_ < is_object<T>, isSupportedContainer<T> >,
isSupported <T> > {};
当我调用isSupported < vector<int> >::value
时,它会生成一堆编译错误(缩短(:
In instantiation of 'struct std::__and_<...>, isSupportedContainer<std::vector<...> > >, isSupported<std::vector<...> > >':
required from 'struct isSupported<std::vector<int> >'
required from /*its call in main()*/
error: invalid use of incomplete type 'std::conditional<true, isSupported<std::vector<int> >, std::__or_<...>, isSupportedContainer<std::vector<...> > > >::type'
struct __and_<_B1, _B2>
^
In /*file containing isSupported and isSupportedContainer*/:
error: declaration of 'std::conditional<true, isSupported<std::vector<int> >, std::__or_<...> >::type'
struct isSupported
^
In function 'int main()':
error: 'value' is not a member of 'isSupported<std::vector<int> >'
cout << isSupported < vector<int> >::value;
^
那么,如何实施这样的检查呢?
示例:假设list
和vector
作为支持的类vector<list<int>>
也受支持,而vector<list<vector<string>>>
不受支持
UPD:工作版本
UPD2:不,不工作
template <class T>
struct isSupported
: public isSupportedSimpleObject<T> {}; //is_object turned out to be a wrong thing
template <template<class> class T, class U>
struct isSupported < T<U> >
: public __and_ < isSupportedContainer<T<U>>,
isSupported <U> > {};
如果在初始替换中使用enable_if
,则可能会简化整个计算。
#include <type_traits>
#include <list>
#include <vector>
#include <string>
template <class T>
struct isSupportedContainer : std::false_type {};
template <class T>
struct isSupportedContainer < std::list<T> > : std::true_type {};
template <class T>
struct isSupportedContainer < std::vector<T> > : std::true_type {};
template <class T, typename = void> // #1
struct isSupported : std::integral_constant<bool, std::is_object<T>::value> {};
template <class Cont> // #2
struct isSupported<Cont, typename std::enable_if<isSupportedContainer<Cont>::value>::type>
: isSupported<typename Cont::value_type> {};
int main() {
static_assert(isSupported<std::vector<int>>::value,"");
static_assert(isSupported<std::vector<std::list<int>>>::value,"");
static_assert(isSupported<std::string>::value,"");
static_assert(!isSupported<int&>::value,"");
return 0;
}
现场演示
这种技术(如果它确实是你所追求的(是基于std::void_t
被添加到 C++17 中的原则
要点如下:
- 主模板定义接受两个类型参数。 第一个命名为
T
,另一个未命名,默认类型为void
。此版本仅检查您的基本情况。 - 实例化模板时,编译器将主实例匹配
isSupported<YourType, void>
。
现在编译器检查是否有任何与参数类型匹配的专用化<YourType, void>
,因此它会查看提供的专用化。std::enable_if
用于确定它的类型实际上是一个受支持的容器,如果是这样,它返回void
,并且我们匹配最初推导出的类型<YourType, void>
.因此,编译器将专用化作为更好的匹配,我们进行递归检查。 - 但是,如果提供的类型不是受支持的容器,则
std::enable_if
没有type
成员,SFINAE 将启动。替换失败,我们返回到在 (1( 中找到的基本情况,它执行基本检查。
相关文章:
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 从类型列表中递归删除重复项会导致编译器堆空间错误 (VS2017)
- 此递归模板类型定义是否有效C++?
- 递归函数的返回类型推导
- 在迭代模板类型列表时无法停止递归
- 如何使用common_type和模板递归类型重载运算符+
- C++ 相互递归的变体类型(再次)
- C++ 引用类型作为递归函数参数
- 我的编辑距离递归代码中的字符类型有问题
- 区分递归类型的结合
- 具有类型名的模板的递归实例化
- C 递归类型定义
- C++递归类型特征
- C++ std::函数,返回它自己的类型(再次递归类型)
- 递归类型真的是构建不连续的任意大小数据结构的唯一方法吗
- 使用模板进行递归类型检查
- 传递的可变模板递归类型
- 使用模板进行递归类型上转换
- 是否可以C++递归类型定义,特别是我可以在 T 的定义中放置一个向量<T>吗?
- decltype,重载运算符的递归类型推导