解包类范围?

时间:2013-07-26 01:04:34

标签: c++ c++11 variadic-templates

考虑以下示例:

#include <iostream>
#include <type_traits>

template <typename Type>
struct Something
{
    template <typename OtherType> 
    static constexpr bool same()
    {return std::is_same<Type, OtherType>::value;}
};

template <class Type>
struct Example
{
    static_assert(Type::template same<double>(), "ERROR");
};

int main()
{
    Example<Something<double>> example;
    return 0;
}

static_assert通过执行same()函数检查传递的类型是否满足某些条件。

现在考虑可以将多个Types传递给Example

#include <iostream>
#include <type_traits>

template <typename Type>
struct Something
{
    template <typename OtherType> 
    static constexpr bool same()
    {return std::is_same<Type, OtherType>::value;}
};

template <class... Types>
struct Example
{
    static_assert(/* SOMETHING */, "ERROR");
};

int main()
{
    Example<Something<double>> example;
    return 0;
}

是否有一个工作语法而不是SOMETHING来检查条件是否在所有类型上得到验证(没有一堆辅助函数:我知道可以这样做但我不知道是否有另一种方式(比如在某处使用简单的拆包......)

2 个答案:

答案 0 :(得分:1)

您可以使用参数包唯一可以将其作为一组参数解压缩到函数中。所以不,没有助手就不能这样做。

如果您允许辅助功能,则有一千种方法可以执行此操作。最明显的是某种logical_and

template<class first, class ...rest>
constexpr bool logical_and(first f, rest... r)
{return bool(f) && logical_and(std::forward<rest>(r)...));}
//                           ^unpack the rest recursively^

template<class last>
constexpr bool logical_and(last l)
{return bool(l);}

template <class... Types>
struct Example
{
    static_assert(logical_and(Something<double>::same<Types>()...), "ERROR");
    //                        ^unpack the results to the function^
};

这是完全未经测试的,可能不会按原样编译

答案 1 :(得分:0)

只需专门化即可完成辅助功能 template Example

如果在现实世界中Example是你的一个班级 不想仅仅为了变量而专攻 static_assert然后您可以封装可变参数static_assert 在自己的模板专业化和你的真实世界类 继承相应的实例化。这是一个例子 只是专门化Example

#include <iostream>
#include <type_traits>

template <typename Type>
struct Something
{
    template <typename OtherType> 
    static constexpr bool same()
    {return std::is_same<Type, OtherType>::value;}
};

template<class ...Types>
struct Example;

template<>
struct Example<>{};

template<class T>
struct Example<T>
{
    static_assert(T::template same<double>(), "ERROR");
};

template<class First, class ...Rest>
struct Example<First,Rest...> : Example<Rest...>
{
    static_assert(First::template same<double>(), "ERROR");
};

int main()
{
    Example<Something<double>> example0; // OK
    Example<Something<double>,Something<double>> example1; // OK
    Example<Something<int>> example2; // Error
    Example<Something<double>,Something<int>> example3; // Error
    Example<Something<double>,Something<double>,Something<int>> example4; // Error
    Example<Something<double>,Something<int>,Something<double>> example5; // Error
    return 0;
}