39

如何制作一个类模板来返回其任何可变参数类型是否等于第一个类型。我希望能够做到这一点:

is_same<T, A, B, C>::value; // true if T is one of A, B or C

如果T等于其中任何一种类型,则其静态value成员将为true,否则为false。我怎样才能做到这一点?

4

6 回答 6

39

使用 C++17 简洁明了:

template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};

和双重:

template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};

使用折叠表达式的变体:

template <class T, class... Ts>
struct is_any : std::bool_constant<(std::is_same_v<T, Ts> || ...)> {};

template <class T, class... Ts>
struct are_same : std::bool_constant<(std::is_same_v<T, Ts> && ...)> {};
于 2016-09-17T18:54:44.127 回答
34

使用模板递归:

template<typename T, typename... Rest>
struct is_any : std::false_type {};

template<typename T, typename First>
struct is_any<T, First> : std::is_same<T, First> {};

template<typename T, typename First, typename... Rest>
struct is_any<T, First, Rest...>
    : std::integral_constant<bool, std::is_same<T, First>::value || is_any<T, Rest...>::value>
{};

static_assert(is_any<int, char, double, int>::value, "error 1");   // OK
static_assert(is_any<int, char, double, short>::value, "error 2"); // error
于 2013-06-10T20:45:59.873 回答
15

在 C++17 中,您有一个更好的解决方案,使用模板变量和折叠表达式:

template<class T, class... Rest>
inline constexpr bool are_all_same = (std::is_same_v<T, Rest> && ...);

并且用法也比所有其他示例更简单:

are_all_same<T, A, B, C>

::value,没有括号!

于 2018-09-14T08:39:00.987 回答
7

像这样的东西。首先,一个小的元编程库,因为它一般添加了两行代码:

template<template<typename,typename>class checker, typename... Ts>
struct is_any_to_first : std::false_type {};

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts>
struct is_any_to_first<checker, T0, T1, Ts...> :
  std::integral_constant< bool, checker<T0, T1>::value || is_any_to_first<checker, T0, Ts...>::value>
{};

然后是 2 行实现is_any_same_to_first

template<typename... Ts>
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >;

为了完整起见,原始is_all的 也可能被证明是有用的:

template<template<typename,typename>class checker, typename... Ts>
struct is_all : std::true_type {};

template<template<typename,typename>class checker, typename T0, typename T1, typename... Ts>
struct is_all<checker, T0, T1, Ts...> :
  std::integral_constant< bool, checker<T0, T1>::value && is_all<checker, T0, Ts...>::value>
{};

template<typename... Ts>
using is_all_same = is_all< std::is_same, Ts... >;

的活生生的例子is_all_same

请注意,调用is_any_same_to_first任何不太明确的内容都是自找麻烦。2/3 试图回答这个问题的人,包括我在内,都认为这is_same<A,B,C>是真的,只要这三个都是同一类型!

于 2013-06-10T20:38:20.673 回答
3

使用宽松的 C++14 constexpr 函数,这些类型的东西更容易编码,而且编译起来也可能更快,所以你可以这样写:

template <class T, class ... Candidates>
constexpr bool is_all_same() {
    bool pairs[] = {std::is_same<T,Candidates>::value...};
    for(bool p: pairs) if(!p) return false;
    return true;
}

template <class T, class ... Candidates>
constexpr bool is_any_same() {
    bool pairs[] = {std::is_same<T,Candidates>::value...};
    for(bool p: pairs) if(p) return true;
    return false;
}

这是因为在 C++14 中 constexpr 函数可以有 for 循环。

于 2016-08-18T14:37:44.957 回答
0

通用的版本:

  • 自 C++11 起

  • 没有依赖项(#include <type_traits>不需要)

  • 只有一个名称is_same适用于 n 类型(is_same_all不需要)

template <typename First, typename Second, typename ... Next>
struct is_same {

    template <typename A, typename B>
    struct is_same_min {
        enum { value = false };
    };

    template <typename A>
    struct is_same_min<A,A> {
        enum { value = true };
    };

    template <typename X, typename Y>
    constexpr static bool check() {
        return is_same_min<X,Y>::value;
    };

    template <typename X, typename Y, typename Z, typename ... K>
    constexpr static bool check() {
        return is_same_min<X,Y>::value and check<Y, Z, K...>();
    };

    enum { value = check<First, Second, Next...>() };
};

只需使用is_same<T1,T2,T3...>::value

于 2019-07-10T18:38:55.707 回答