【问题标题】:Check if a type is passed in variadic template parameter pack检查类型是否在可变参数模板参数包中传递
【发布时间】:2016-03-10 01:12:33
【问题描述】:

我在某处听说过,使用新的 C++1z 语法,很容易检查是否在可变参数模板参数包中传递了一个类型——显然你可以使用接近一行的代码来做到这一点。这是真的?这些相关的特征是什么? (我尝试查看折叠表达式,但看不到如何在该问题中使用它们...)

以下是我在 C++11 中解决问题的方法以供参考:

#include <type_traits>


template<typename T, typename ...Ts>
struct contains;

template<typename T>
struct contains<T> {
    static constexpr bool value = false;
};

template<typename T1, typename T2, typename ...Ts>
struct contains<T1, T2, Ts...> {
    static constexpr bool value = std::is_same<T1, T2>::value ? true : contains<T1, Ts...>::value;
};

【问题讨论】:

  • 之前我没有看到你说你无法弄清楚折叠表达式语法的部分,我也为此添加了一个示例。

标签: c++ templates typetraits c++17


【解决方案1】:

您正在寻找std::disjunction。它在N4564 [meta.logical] 中指定。

#include <type_traits>

template<typename T, typename... Ts>
constexpr bool contains()
{ return std::disjunction_v<std::is_same<T, Ts>...>; }

static_assert(    contains<int,      bool, char, int, long>());
static_assert(    contains<bool,     bool, char, int, long>());
static_assert(    contains<long,     bool, char, int, long>());
static_assert(not contains<unsigned, bool, char, int, long>());

Live demo


或者,适应struct

template<typename T, typename... Ts>
struct contains : std::disjunction<std::is_same<T, Ts>...>
{};

或者,使用折叠表达式

template<typename T, typename... Ts>
struct contains : std::bool_constant<(std::is_same<T, Ts>{} || ...)>
{};

Live demo

【讨论】:

  • 好一个!我通常会看到由继承委托的值元函数,它要短得多:template&lt;...&gt; struct contains : std::disjunction&lt;...&gt; {};
  • @Quentin 谢谢,好多了。我太想从函数版本中使用disjunction_v :)
  • 在您的折叠表达式中 - struct contains : std::bool_constant&lt;(std::is_same&lt;T, Ts&gt;{} || ...)&gt; - 语法 std::is_same&lt;T, Ts&gt;{} 是什么意思? (我的意思是,std::is_same&lt;T,Ts&gt; 是一个结构,它在其value 成员变量中包含真或假值。{} 根据哪个语法规则从结构中提取这个value?)
  • @qiubit {}direct-list-initializing is_same 实例,换句话说,就是在构造它。 is_same 有一个隐式布尔转换运算符,它继承自 integral_constant,因此该表达式产生一个布尔值。你也可以改写std::is_same&lt;T, Ts&gt;::value
  • 既然我们在 17 个区域中使用 fold 表达式,我们不妨写成is_same_v
【解决方案2】:

如果您绑定到 C++11,则不能使用 std::disjunction 或折叠表达式。但是,滚动您自己的any_is_same 相当简单:

template<typename same, typename first,typename...more> 
struct any_is_same {
    static const bool value = std::is_same<same,first>::value || 
                              any_is_same<first,more...>::value; 
};

template<typename same,typename first> 
struct any_is_same<same,first> : std::is_same<same,first> {};


int main(){
    std::cout << any_is_same<int, int,double,float>::value << "\n";
    std::cout << any_is_same<std::string, int,double,float>::value << "\n";
}

Live Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2017-07-13
    • 1970-01-01
    • 2017-03-18
    相关资源
    最近更新 更多