如何制作一个可变的is_same?

Me *_*d I 33 c++ templates variadic-templates c++11

如何创建一个类模板,返回其任何可变类型是否等于第一个类型.我希望能够这样做:

is_same<T, A, B, C>::value; // true if T is one of A, B or C
Run Code Online (Sandbox Code Playgroud)

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

sya*_*yam 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
Run Code Online (Sandbox Code Playgroud)


mav*_*vam 24

C++ 17简洁明了:

template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};
Run Code Online (Sandbox Code Playgroud)

双重:

template <class T, class... Ts>
struct are_same : std::conjunction<std::is_same<T, Ts>...> {};
Run Code Online (Sandbox Code Playgroud)

使用折叠表达式的变体:

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> && ...)> {};
Run Code Online (Sandbox Code Playgroud)

  • 这比检查的答案更清晰,我觉得它应该得到复选标记,即使问题有一个 c++11 标签 (3认同)

Joa*_*ald 8

在C ++ 17中,您可以使用模板变量和fold表达式得到更好的解决方案:

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

而且用法也比其他所有示例都简单:

are_all_same<T, A, B, C>
Run Code Online (Sandbox Code Playgroud)

::value,没有括号!


Yak*_*ont 7

像这样的东西.首先,一个小的元编程库,因为它通常添加2行来完成它:

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>
{};
Run Code Online (Sandbox Code Playgroud)

然后是2行执行is_any_same_to_first:

template<typename... Ts>
using is_any_same_to_first = is_any_to_first< std::is_same, Ts... >;
Run Code Online (Sandbox Code Playgroud)

而为了完整性,原件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... >;
Run Code Online (Sandbox Code Playgroud)

活生生的例子is_all_same.

请注意,调用is_any_same_to_first任何不太明确的东西都会遇到麻烦.2/3试图回答这个问题的人,包括我在内,假设is_same<A,B,C>如果所有三个都是同一类型,那就是真的!