首页 > 解决方案 > 递归模板参数包编程

问题描述

我对 C++ 模板编程很陌生。我想设计一个功能element例如

  1. element<3, 3, 3, 3, 3>将返回 3
  2. element<3, 3, 2>将使断言失败

    #include <iostream>
    #include <cstdlib>
    
    namespace meta
    {       
      template<typename T>
      constexpr T element(T x)
      {
        return x;
      }
    
      template<typename T, typename... Ts>
      constexpr T element(T x, Ts... xs)
      {
        constexpr T oth = element(xs...);             // $C$
        static_assert(oth == x, "element Mismatch");
        return x;
      }
    
      template<int... DIMS>
      void get_elements()
      {
        std::cout << "elements " << element(DIMS...); // $A$
      }
    }
    
    int main(int argc, char ** argv)
    {
      meta::get_elements<2, 3, 4>();                  // $B$
    
      static constexpr int D1 = 3, D2 = 3;
    
      meta::get_elements<D1, D2>();
    }
    

但是 GCC withstd=c++14失败了

在 'constexpr T meta::element(T, Ts ...) [with T = int; Ts = {int,int}]':

$A$: 需要从 'void meta::get_elements() [with int ...DIMS = {2, 3, 4}]'</p>

$B$:从这里需要

$C$: 错误: 'xs#0' 不是常量表达式

$C$: 错误: 'xs#1' 不是常量表达式

我想利用递归对列表中的每个模板参数执行相等检查,如果它们都相等则返回其中一个。

标签: c++variadic-templates

解决方案


这是 C++17 中的一个简单解决方案:

template <int Head, int... Tail> struct element
{
    static_assert((... && (Head == Tail)), "missmatch elements");
    static constexpr auto value = Head;
};

template <int... I> constexpr auto element_v = element<I...>::value;

auto test()
{
    // element_v<3, 3, 1>; // assert fail

    constexpr int A = 3, B = 3;
    return element_v<3, 3, A, B>;
}

在godbolt上看到它


推荐阅读