使用模板进行递归类型检查

时间:2016-02-14 10:51:34

标签: c++ templates recursion typetraits

我有几个类型检查模板:来自is_object的{​​{1}}和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>>不是

UPD:工作版本
UPD2:不,不工作

vector<list<vector<string>>>

1 个答案:

答案 0 :(得分:2)

如果在初始替换中使用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;
}

Live Demo

这种技术(如果它确实是你所追求的)是基于std::void_t被添加到C ++ 17的原则

关键点如下:

  1. 主模板定义接受两个类型参数。第一个名称为T,另一个名称为未命名,默认类型为void。这个版本只是检查你的基本情况。
  2. 实例化模板时,编译器与主实例isSupported<YourType, void>匹配 现在,编译器检查是否存在与参数类型<YourType, void>匹配的任何特化,因此它会查看提供的特化。 std::enable_if用于确定类型实际上是受支持的容器,如果返回void,我们会匹配最初推断的类型<YourType, void>。因此编译器将专门化作为更好的匹配,我们进行递归检查。
  3. 但是,如果提供的类型不是受支持的容器,则std::enable_if没有type成员,并且SFINAE会启动。替换失败,我们将返回到我们在(1)中找到的基本情况,进行基本检查。