C++ 检测类型是否为std::tuple?
目前我有两个功能:C++ 检测类型是否为std::tuple?,c++,templates,c++11,tuples,typetraits,C++,Templates,C++11,Tuples,Typetraits,目前我有两个功能: template<typename Type> bool f(Type* x); template<typename... List> bool f(std::tuple<List...>* x); 模板bool f(类型*x); 模板boolf(std::tuple*x); 有没有办法用一个额外的模板参数来合并这两个函数,该参数指示传递的类型是否为元组 template<typename Type, bool IsTuple =
template<typename Type> bool f(Type* x);
template<typename... List> bool f(std::tuple<List...>* x);
模板bool f(类型*x);
模板boolf(std::tuple*x);
有没有办法用一个额外的模板参数来合并这两个函数,该参数指示传递的类型是否为元组
template<typename Type, bool IsTuple = /* SOMETHING */> bool f(Type* x);
模板bool f(类型*x);
当然可以,使用(从以下位置获取并修复链接):
模板
布尔f(x型);
但问题是,你真的想要这样吗?通常,如果需要知道类型是否为元组,则需要对元组进行特殊处理,这通常与它的模板参数有关。因此,您可能希望坚持使用重载版本
编辑:因为您提到您只需要一小部分专用,所以我建议重载,但仅适用于小的特殊部分:
template<class T>
bool f(T* x){
// common parts...
f_special_part(x);
// common parts...
}
模板
布尔f(T*x){
//公共部分。。。
f_特殊部分(x);
//公共部分。。。
}
与
模板
特殊部分无效(T*x){/*一般情况*/}
模板
void f_特殊部分(std::tuple*x){/*特殊tuple case*/}
您可以让您的函数服从于另一个函数:
template<typename Type,bool IsTuple> bool f(Type *x);
template<typename Type>
inline bool f(Type* x) { return f<Type,false>(x); }
template<typename... List>
inline bool f(std::tuple<List...>* x) { return f<std::tuple<List...>,true>(x); }
模板bool f(类型*x);
模板
内联boolf(Type*x){返回f(x);}
模板
内联boolf(std::tuple*x){返回f(x);}
对于C++17,下面是一个使用
输出:
一个元组不是元组
部分解决方案来自于一个在这里找到的:使用C++11,这是我首选的模式:
// IsTuple<T>()
template <typename T>
struct IsTupleImpl : std::false_type {};
template <typename... U>
struct IsTupleImpl<std::tuple <U...>> : std::true_type {};
template <typename T>
constexpr bool IsTuple() {
return IsTupleImpl<decay_t<T>>::value;
}
//IsTuple()
模板
结构IsTupleImpl:std::false_type{};
模板
结构IsTupleImpl:std::true_type{};
模板
constexpr bool IsTuple(){
返回IsTupleImpl::value;
}
效果很好。没有依赖项(我不能使用Boost)。可能会有点晚,但您也可以这样做,使用更现代的c++17样式和模板变量:
template <typename T>
constexpr bool IsTuple = false;
template<typename ... types>
constexpr bool IsTuple<std::tuple<types...>> = true;
模板
constexpr bool IsTuple=false;
模板
constexpr bool IsTuple=true;
还有一些测试
struct TestStruct{};
static_assert(IsTuple<int> == false, "Doesn't work with literal.");
static_assert(IsTuple<TestStruct> == false, "Doesn't work with classes.");
static_assert(IsTuple<std::tuple<int, char>>, "Doesn't work with plain tuple.");
static_assert(IsTuple<std::tuple<int&, char&>>, "Doesn't work with lvalue references");
static_assert(IsTuple<std::tuple<int&&, char&&>>, "Doesn't work with rvalue references");
struct TestStruct{};
静态_断言(IsTuple==false,“不与文本一起工作”);
静态_断言(IsTuple==false,“不与类一起工作”);
静态断言(IsTuple,“不适用于普通元组”);
静态断言(IsTuple,“不适用于左值引用”);
静态断言(IsTuple,“不适用于右值引用”);
你可以在这里看
编辑:
您需要运行std::Decage、std::remove_volatile、std::remove_const来处理特殊情况。在正常情况下,这可能是危险的,最好是专门化。但此函数是一个大函数,如果内部更改元组类型与否,则只有一个小的
。使用额外的模板参数也意味着可以显式调用f
,或f
,这可以通过检查函数体中的是否为
来避免。@Vincent:那么如果
,我实际上建议使用标记分派而不是运行时。)<代码>静态I/<代码>,我们需要YoooooouIn C++ 17,如果最简洁的解决方案,你可以使用<代码> CONTXPR,因此最好使用。
template<typename Type> bool f(Type* x) {
if constexpr (is_tuple<Type>::value) {
std::cout << "A tuple!!\n";
return true;
}
std::cout << "Not a tuple\n";
return false;
}
f(&some_tuple);
f(&some_object);
// IsTuple<T>()
template <typename T>
struct IsTupleImpl : std::false_type {};
template <typename... U>
struct IsTupleImpl<std::tuple <U...>> : std::true_type {};
template <typename T>
constexpr bool IsTuple() {
return IsTupleImpl<decay_t<T>>::value;
}
template <typename T>
constexpr bool IsTuple = false;
template<typename ... types>
constexpr bool IsTuple<std::tuple<types...>> = true;
struct TestStruct{};
static_assert(IsTuple<int> == false, "Doesn't work with literal.");
static_assert(IsTuple<TestStruct> == false, "Doesn't work with classes.");
static_assert(IsTuple<std::tuple<int, char>>, "Doesn't work with plain tuple.");
static_assert(IsTuple<std::tuple<int&, char&>>, "Doesn't work with lvalue references");
static_assert(IsTuple<std::tuple<int&&, char&&>>, "Doesn't work with rvalue references");