17

目前我有两个功能:

template<typename Type> bool f(Type* x);
template<typename... List> bool f(std::tuple<List...>* x);

有没有办法将这两个函数与一个额外的模板参数合并,该参数指示传递的类型是否是一个元组?

template<typename Type, bool IsTuple = /* SOMETHING */> bool f(Type* x);
4

5 回答 5

18

当然,使用(从此处is_specialization_of获取并修复的链接):

template<typename Type, bool IsTuple = is_specialization_of<Type, std::tuple>::value>
bool f(Type* x);

然而,问题是,你真的想要这样吗?通常,如果您需要知道一个类型是否是元组,您需要对元组进行特殊处理,这通常与它的模板参数有关。因此,您可能希望坚持使用重载版本。

编辑:既然你提到你只需要一小部分专门,我建议重载,但只适用于小的特殊部分:

template<class T>
bool f(T* x){
  // common parts...
  f_special_part(x);
  // common parts...
}

template<class T>
void f_special_part(T* x){ /* general case */ }

template<class... Args>
void f_special_part(std::tuple<Args...>* x){ /* special tuple case */ }
于 2012-10-27T14:35:26.387 回答
11

使用 C++17,这是一个相当简单的解决方案,使用if constexpr

template <typename> struct is_tuple: std::false_type {};

template <typename ...T> struct is_tuple<std::tuple<T...>>: std::true_type {};

然后您可以执行以下操作:

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

输出:

一个元组!!
不是元组


部分来自此处找到的答案的解决方案:如何知道类型是否是 std::vector 的特化?

于 2018-01-26T09:03:28.293 回答
5

你可以让你的函数服从另一个函数:

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); }
于 2012-10-27T14:49:20.687 回答
5

对于 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;
}

效果很好。没有依赖项(我不能使用 Boost)。

于 2018-06-28T01:45:17.960 回答
4

可能有点晚了,但你也可以用更现代的 c++17 风格和模板变量做这样的事情:

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

你可以在这里查看https://godbolt.org/z/FYI1jS

编辑:您将需要运行 std::decay、std::remove_volatile、std::remove_const 来处理特殊情况。

于 2018-09-12T09:10:07.583 回答