检查C++ 0x参数包是否包含类型

Sum*_*ant 7 c++ templates metaprogramming variadic c++11

我想知道C++ 0x是否提供了任何内置功能来检查可变参数模板的参数包是否包含特定类型.今天,如果你使用boost :: mpl :: vector作为variadic模板的替代品,可以用boost ::: mpl :: contains来实现这个目的.但是,它有严重的编译时间开销.我想,C++ 0x对std :: is_same有编译器级支持.所以我在想是否编译器中也支持如下的泛化.

template <typename... Args, typename What>
struct is_present
{
  enum { value = (What in Args...)? 1 : 0 };
};
Run Code Online (Sandbox Code Playgroud)

Kai*_*zke 13

幸运的是,C++ 标准已经发展。使用 C++1z aka C++17,您最终可以轻松地迭代参数包。所以答案的代码(几乎)和问题中建议的一样简单:

template<typename What, typename ... Args>
struct is_present {
    static constexpr bool value {(std::is_same_v<What, Args> || ...)};
};
Run Code Online (Sandbox Code Playgroud)

奇怪的外观(std::is_same_v<What, Args> || ...)由编译器在内部扩展为(std::is_same_v<What, Args[0]> || std::is_same_v<What, Args[1]> || ...),这正是您想要的。它甚至可以false使用空Args参数包正确产生。

甚至可以在函数或方法中内联进行整个检查 - 不再需要辅助结构:

template<typename T, typename ... List>
void foo(T t, List ... lst)
{
    if constexpr((std::is_same_v<T, List> || ...)) {
        std::cout << "T is in List" << std::endl;
    } else {
        std::cout << "T is not in List" << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这是从另一个问题中提取的,该问题被标记为该问题的副本。由于这是本主题的“规范”问题,因此我在此处添加了重要信息。

  • 很好的解决方案。它可以简化一点:`template&lt;typename What, typename... Args&gt; constexpr inline bool is_present_v = (std::is_same_v&lt;What, Args&gt; || ...);` (2认同)

snk*_*kid 6

不,您必须对可变参数模板使用(部分)专业化来进行编译时计算,如下所示:

#include <type_traits>

template < typename Tp, typename... List >
struct contains : std::true_type {};

template < typename Tp, typename Head, typename... Rest >
struct contains<Tp, Head, Rest...>
: std::conditional< std::is_same<Tp, Head>::value,
    std::true_type,
    contains<Tp, Rest...>
>::type {};

template < typename Tp >
struct contains<Tp> : std::false_type {};
Run Code Online (Sandbox Code Playgroud)

可变参数模板只有一种其他内在操作,即计算参数列表长度的 sizeof 运算符的特殊形式,例如:

template < typename... Types >
struct typelist_len
{
   const static size_t value = sizeof...(Types);
};
Run Code Online (Sandbox Code Playgroud)

你从哪里得到 boost mpl 的“它有严重的编译时间开销”?我希望你在这里不仅仅是做假设。Boost mpl 使用诸如延迟模板实例化之类的技术来尝试减少编译时间,而不是像原始模板元编程那样爆炸。

  • 我更喜欢使用专业化技术来匹配它:`template&lt;typename M, typename ...L&gt; struct C : std::false_type {}; 模板&lt;typename M, typename ...L&gt; struct C&lt;M, M, L...&gt; : std::true_type {}; template&lt;typename M, typename L1, typename ...L&gt; struct C&lt;M, L1, L...&gt; : C&lt;M, L...&gt; {};` (5认同)