Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 检测类型是否为std::tuple?_C++_Templates_C++11_Tuples_Typetraits - Fatal编程技术网

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");