如何检查传递给varadic函数的参数的类型
How to check the type of passed arguments to variadic function
我对可变模板很陌生,为了学习,请考虑以下函数
template <typename T, typename... args>
T* make_arr(args... arg) {
// Code to check if passed args are of the same type
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
}
我有两个问题:
- 我希望函数是模板化的,并且我希望传递的参数是相同类型的,所以问题是:是否可以检查传递的参数是否是相同类型
- 是否可以通过推导
args...
的类型来推导数组指针的类型,我的意思是不使用<typename T>
。。。我使用了decltype(arg),但它不起作用
注意:如果标题问题不合适,请编辑。。。感谢
我找到的唯一方法是使用SFINAE 制作一个助手函数
//Basic function
template<typename T>
void allsame(T) {}
//Recursive function
template<typename T, typename T2, typename... Ts,
typename = std::enable_if_t<std::is_same<T, T2>::value>>
void allsame(T arg, T2 arg2, Ts... args)
{
allsame(arg2, args...);
}
然后你可以这样称呼它:
allsame(arg...);
如果类型不相同,编译器将抛出一个错误。
对于2),您可以修改allsame
以返回类型。这个函数唯一的缺点是,如果类型不是默认可构造的,它就不起作用。
template<typename T>
T allsame(T) { return{}; }
T allsame(T arg, T2 arg2, Ts... args)
然后,您可以decltype(allsame(args...))
来获得类型
首先,您需要这些包括:
#include <type_traits>
#include <tuple>
然后,让我们声明可变模板来检测类型是否相同:
template <typename ... args>
struct all_same : public std::false_type {};
template <typename T>
struct all_same<T> : public std::true_type {};
template <typename T, typename ... args>
struct all_same<T, T, args...> : public all_same<T, args ... > {};
现在我们可以使用static_assert
来检测参数类型是否相同:
template <typename T, typename... args>
T* make_arr(args... arg) {
// Code to check if passed args are of the same type
static_assert(all_same<args ...>::value, "Params must have same types");
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
};
最后,让我们把函数的返回类型作为第一类参数——如果所有类型都相同,我们可以取其中的任何一个。我们使用std::tuple
进行
template <typename... args>
typename std::tuple_element<0, std::tuple<args...> >::type * make_arr(args... arg) {
// Code to check if passed args are of the same type
static_assert(all_same<args ...>::value, "Params must have same types");
typedef typename std::tuple_element<0, std::tuple<args...> >::type T;
T* arr = new T[sizeof...(arg)]{ arg... };
return arr;
};
从constexpr bool
函数开始,检查所有布尔值是否为true。当检查所有is_same
调用是否为true
时,这将非常有用。
constexpr bool all() {
return true;
}
template<typename ...B>
constexpr bool all(bool b, B... bs) {
return b && all(bs...);
}
总之,这里是make_arr
函数:
template <typename... args
, class ...
, typename T = std::tuple_element_t<0, std::tuple<args...>>
, typename = std::enable_if_t< all(std::is_same<T, args>{}...) >
>
T* make_arr(args&&... arg) {
static_assert( all(std::is_same<T, args>{}...) ,"");
T* arr = new T[sizeof...(arg)]{ std::forward<args>(arg)... };
return arr;
}
一些评论:
- 使用完美的转发
&&
和std::forward
,以避免在您的类型较大时出现潜在的副本 - 通过创建CCD_ 13类型并使用CCD_
- 使用
static_assert
,其中将每种类型与第一种类型进行比较(经由is_same
) - 我想您希望SFINAE"隐藏"此函数,除非类型完全相同。这是通过
typename = std::enable_if_t< ..boolean-expression.. >
实现的 - CCD_ 18基本上是冗余的。它的唯一目的是让开发人员不可能通过手动指定类型(
make_arr<int,char,size_t,bool>(..)
)来欺骗检查。然而,也许这太保守了——static_assert
无论如何都会抓住他们
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 为什么通过通用引用运算符 (&&) 将变量的引用传递给 Varadic 模板函数失败?
- 如何在varadic/template类构造函数中正确使用std::forward
- 如何检查传递给varadic函数的参数的类型
- varadic模板中的函数参数数量与类中的相同
- varadic函数-c++变量参数列表
- std::函数到varadic成员函数,然后绑定varadic模板参数