C++ 如何静态检查模板的类型T是否为std::vector<;U>;,其中U为浮点数、二重数或整数

C++ 如何静态检查模板的类型T是否为std::vector<;U>;,其中U为浮点数、二重数或整数,c++,templates,c++11,vector,variadic-templates,C++,Templates,C++11,Vector,Variadic Templates,我如何检查参数包中的参数的类型是浮点型,双精度,还是标准::向量型 例如,T={int,long,std::vector}就可以了 而T={int,long,std::vector}不是,因为我们不允许std::vector为long double类型 我走了这么远 template<class ...T> void foo(T... t) { static_assert(std::is_same<float, T...>::value

我如何检查参数包中的参数的类型是
浮点型
双精度
,还是
标准::向量型

例如,
T={int,long,std::vector}
就可以了

T={int,long,std::vector}
不是,因为我们不允许
std::vector
long double
类型

我走了这么远

template<class ...T>
void foo(T... t)
{
    static_assert(std::is_same<float, T...>::value
               || std::is_same<double, T...>::value
               || std::is_integral<T...>::value
            /* || std::is_same<std::vector<float/double/integral>, T>::value ? */
               , "unsupported type!");
}

T={}

您可以使用模板专门化创建自己的检查时,我还希望断言成功(即通过构建)。我扩大了检查范围,将
长双精度
包括在内,只是为了减小代码的大小

#include <type_traits>
#include <vector>

template<class T>
struct is_ok {
    static constexpr bool value =
        std::is_floating_point<T>::value ||
        std::is_integral<T>::value;
};

template<class T>
struct is_ok<std::vector<T>> {
    static constexpr bool value =
        std::is_floating_point<T>::value ||
        std::is_integral<T>::value;
};
#包括
#包括
模板
结构正常吗{
静态constexpr布尔值=
std::是\u浮点::值||
std::is_integral::value;
};
模板
结构正常吗{
静态constexpr布尔值=
std::是\u浮点::值||
std::is_integral::value;
};
下面是一个演示:

#include <cstdio>
#define TEST(x) \
    std::printf("%s: %s\n", #x, is_ok<x>::value ? "true" : "false")

int main() {
    TEST(int);
    TEST(float);
    TEST(char *);
    TEST(std::vector<int>);
    TEST(std::vector<float>);
    TEST(std::vector<char *>);
    return 0;
}
#包括
#定义测试(x)\
标准::printf(“%s:%s\n”x,是否确定::值?“真”:“假”)
int main(){
测试(int);
试验(浮子);
测试(字符*);
测试(std::vector);
测试(std::vector);
测试(std::vector);
返回0;
}
输出:

int: true
float: true
char *: false
std::vector<int>: true
std::vector<float>: true
std::vector<char *>: false
int:true
浮动:对
字符*:假
向量:真
向量:真
std::vector:false

您可以使用helper类来完成您想做的事情

template<class ...T> struct is_float_or_integral;

template <typename T> struct is_float_or_integral<T>
{
   static const bool value =
      std::is_integral<T>::value ||
      std::is_floating_point<T>::value;
};

// Use this if you want vector<vector<int>> to be OK.
template <typename T> struct is_float_or_integral<std::vector<T>>
{
   static const bool value = is_float_or_integral<T>::value;
};

// Use this if you don't want vector<vector<int>> to be OK.
template <typename T> struct is_float_or_integral<std::vector<T>>
{
   static const bool value =
      std::is_integral<T>::value ||
      std::is_floating_point<T>::value;
};

template <typename T1, typename ...T> struct is_float_or_integral<T1, T...>
{
   static const bool value =
      is_float_or_integral<T1>::value &&
      is_float_or_integral<T...>::value;
};
模板结构是\u float\u或\u integral;
模板结构是\u float\u或\u integral
{
静态常数布尔值=
std::is_integral::value||
std::is_floating_point::value;
};
//如果您希望vector正常,请使用此选项。
模板结构是\u float\u或\u integral
{
静态常量布尔值=是浮点值或整数::值;
};
//如果不想让vector正常,请使用此选项。
模板结构是\u float\u或\u integral
{
静态常数布尔值=
std::is_integral::value||
std::is_floating_point::value;
};
模板结构是\u float\u或\u integral
{
静态常数布尔值=
是浮点数还是整数::值&&
是浮点数或整数::值;
};
并将其用作:

template<class ...T>
void foo(T... t)
{
   static_assert(is_float_or_integral<T...>::value == true, "Problem");
   //
   // ... Rest of your function.
}
模板
无效foo(T…T)
{
静态断言(是浮点数还是积分::value==true,“问题”);
//
//…你的其他职能。
}

首先编写一个测试一种类型的特征:

template<class T>
struct is_ok : std::is_arithmetic<T> { };

template<class T, class A>
struct is_ok<std::vector<T, A>> : std::is_arithmetic<T> { };

函数重载允许对向量元素类型的限制进行更简单的说明,一个简单的
ignore
helper函数接受参数并丢弃参数,允许您轻松地为每个参数添加相关检查:

#include <type_traits>
#include <vector>

template <typename T>
auto is_valid(T) ->
  std::integral_constant<
    bool,
    std::is_integral<T>::value
      || std::is_same<T, float>::value
      || std::is_same<T, double>::value>;

template <typename T>
auto is_valid(std::vector<T>) ->
  std::integral_constant<
    bool,
    std::is_integral<T>::value
      || std::is_same<T, float>::value
      || std::is_same<T, double>::value>;

void ignore(...) { }

template<class ...T>
void foo(T... t)
{
    ignore([]() {
      static_assert(decltype(is_valid(t))::value, "unsupported type!");
    }...);
}
#包括
#包括
模板
自动有效(T)->
积分常数<
布尔,
std::is_integral::value
||std::值是否相同
||标准::是否相同::值>;
模板
自动有效(标准::向量)->
积分常数<
布尔,
std::is_integral::value
||std::值是否相同
||标准::是否相同::值>;
无效忽略(…){}
模板
无效foo(T…T)
{
忽略([])(){
静态断言(decltype(is_valid(t))::值,“unsupported type!”);
}...);
}

@Dietrich Epp和@T.C.的解决方案很好,除了第一个没有解释如何在我的问题中的可变模板案例中使用它,而后者也没有解释如何将解决方案扩展到多个约束检查(虽然@T.C.后来在评论中提到了这个问题,但在他发表评论之前,我已经使用了他们的合并解决方案)

无论如何,如果有人感兴趣的话,这里是他们的合并解决方案。它还重用了基类型限制,如问题中所述

// base type restrictions
template<class T>
struct is_ok_base
{
    static constexpr bool value =
        std::is_same<float, T>::value
        || std::is_same<double, T>::value
        || std::is_integral<T>::value;
};

// allow any types that is_ok_base accepts
template<class T>
struct is_ok
{
    static constexpr bool value = is_ok_base<T>::value;
};

// allow any types for std::vector that is_ok_base accepts
template<class T>
struct is_ok<std::vector<T>>
{
    // replace is_ok_base<T>::value with is_ok<T>::value if you want to allow
    // nested vectors
    static constexpr bool value = is_ok_base<T>::value;
};

// some boilerplate to make the checks above work with variadic templates
template<bool...> class bool_pack;
template<bool... b>
using all_true = std::is_same<bool_pack<true, b...>, bool_pack<b..., true>>;

// the actual check
template<class ...T>
constexpr void static_type_check()
{
    static_assert(all_true<is_ok<T>::value...>::value, "Unsupported type!");
}

template<class ...T>
void foo(T... t)
{
    static_type_check<T...>(); // or just copypaste the static_assert into here
}
//基类型限制
模板
结构是_ok _base
{
静态constexpr布尔值=
std::值是否相同
||std::值是否相同
||std::is_integral::value;
};
//允许\u ok\u base接受的任何类型
模板
结构正常吗
{
静态constexpr bool value=is_ok_base::value;
};
//允许std::vector的任何类型为_ok_base accepts
模板
结构正常吗
{
//如果要允许,请将is_ok_base::value替换为is_ok::value
//嵌套向量
静态constexpr bool value=is_ok_base::value;
};
//使用可变模板进行上述检查的一些样板
模板类bool_包;
模板
使用all_true=std::is_same;
//实际支票
模板
constexpr void static_type_check()
{
静态断言(all_true::value,“不支持的类型!”);
}
模板
无效foo(T…T)
{
static_type_check();//或者将static_断言复制粘贴到这里
}

向量的
专门化
是否可以
简单地重用
是否可以::value
?@Pradhan:那将允许
标准::向量
通过。就我的“很好重用”而言问题的一部分是,我想我可以为std::is|u same::value | std::is|u same::value | std::is_integral::value
创建一个单独的模板结构并重用它?你能从问题中说明如何在我的
foo
函数中使用它吗?不太确定如何将其应用于可变模板类型。@FlyingHat:Us把它放在
静态断言中
,就像你已经拥有的那样。我实际上需要
std::is|u same | std::is|u same | std::is_integral
而不是
std::is_算术
替换
struct是ok:std::is_算术{
导致当用双精度调用
foo
时,
对“is_ok::value”的引用是不明确的。
但是你的答案与@Dietrich Epp的结合是完美的。@FlyingHat从这样的多个特征派生是不可行的。要么从
std::integral_常量派生,要么专门化
is_ok
等派生from
std::false\u type
#include <type_traits>
#include <vector>

template <typename T>
auto is_valid(T) ->
  std::integral_constant<
    bool,
    std::is_integral<T>::value
      || std::is_same<T, float>::value
      || std::is_same<T, double>::value>;

template <typename T>
auto is_valid(std::vector<T>) ->
  std::integral_constant<
    bool,
    std::is_integral<T>::value
      || std::is_same<T, float>::value
      || std::is_same<T, double>::value>;

void ignore(...) { }

template<class ...T>
void foo(T... t)
{
    ignore([]() {
      static_assert(decltype(is_valid(t))::value, "unsupported type!");
    }...);
}
// base type restrictions
template<class T>
struct is_ok_base
{
    static constexpr bool value =
        std::is_same<float, T>::value
        || std::is_same<double, T>::value
        || std::is_integral<T>::value;
};

// allow any types that is_ok_base accepts
template<class T>
struct is_ok
{
    static constexpr bool value = is_ok_base<T>::value;
};

// allow any types for std::vector that is_ok_base accepts
template<class T>
struct is_ok<std::vector<T>>
{
    // replace is_ok_base<T>::value with is_ok<T>::value if you want to allow
    // nested vectors
    static constexpr bool value = is_ok_base<T>::value;
};

// some boilerplate to make the checks above work with variadic templates
template<bool...> class bool_pack;
template<bool... b>
using all_true = std::is_same<bool_pack<true, b...>, bool_pack<b..., true>>;

// the actual check
template<class ...T>
constexpr void static_type_check()
{
    static_assert(all_true<is_ok<T>::value...>::value, "Unsupported type!");
}

template<class ...T>
void foo(T... t)
{
    static_type_check<T...>(); // or just copypaste the static_assert into here
}