【问题标题】:Iterate over template int迭代模板 int
【发布时间】:2019-03-04 21:59:32
【问题描述】:

我有一个函数:

template<class Real, int N>
constexpr std::array<Real, N> get_array();

我想在许多类型和许多整数上对其进行测试。在伪代码中:

auto types = {float, double, long double};
for(int i = 0; i < 25; ++i) {
   for (type : types) {
        auto arr = get_array<type, i>();
        // test arr
   }
}

显然这不会编译。有没有办法修补循环以使其可以遍历数组?

【问题讨论】:

  • 您希望在编译时使用模板元编程来实现。
  • GoogleTest 框架有类型化测试和类型参数化测试:github.com/google/googletest/blob/master/googletest/docs/…。或者,因为只有 3 种类型要测试,所以只做 get_array&lt;float, i&gt;; get_array&lt;double,i&gt; 等不会有害。
  • @PaulEvans:是的,我愿意。
  • @Yksisarvinen:Googletest 很棒,但测试只是为了激发目标。

标签: c++ templates c++17 template-meta-programming boost-hana


【解决方案1】:

既然你已经标记了 Boost.Hana,我们可以直接使用它:

auto types = hana::tuple_t<float, double, long double>;
hana::for_each(types, [](auto type){
    hana::for_each(std::make_index_sequence<25>(), [=](auto idx){
        // here type is an object that denotes the type and
        // idx is an integral constant that denotes the next value

        get_array<typename decltype(type)::type, idx>();
    });
});

【讨论】:

  • 为了完整起见,什么是最小标题? (如果您不知道的话,我会查找并编辑。)
  • @user14717 &lt;boost/hana.hpp&gt;?
  • 这是一个聚合头;通常我喜欢只包含我需要检查编译时间的库的一部分。不过没什么大不了的。
  • 我得到:错误:'type_t' 不是 'boost::hana' 的成员,使用 g++-8 并开发 hana。
  • 很确定是tuple_t
【解决方案2】:

公认的答案很好,但如果您不想污染调用堆栈,最好在处理实际运行时内容之前完成所有可能的处理。

此处的示例使用 hana::cartesian_product,这对于临时用例可能有点过分,但您可以使用嵌套的 hana::unpacks 来获得相同的效果。

这是一个工作示例:

https://godbolt.org/z/zKwpqe

#include <array>
#include <boost/hana/assert.hpp>
#include <boost/hana/at.hpp>
#include <boost/hana/cartesian_product.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/range.hpp>
#include <boost/hana/transform.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>

namespace hana = boost::hana;

template <typename Real, int N>
constexpr std::array<Real, N> get_array() {
  return {};
}

int main() {
  auto types   = hana::tuple_t<float, double, long, double>;
  auto lengths = hana::to_tuple(hana::range_c<int, 0, 4>);
  auto tls = hana::cartesian_product(hana::make_tuple(types, lengths));
  auto get_array_fns = hana::transform(tls, [](auto pair) {
    return [] {
      return get_array<typename decltype(+hana::at_c<0>(pair))::type,
                       decltype(+hana::at_c<1>(pair))::value>();
      };
  });

  hana::for_each(get_array_fns, [](auto get_array) {
    auto arr = get_array();
    // test arr 
  });

  auto result_types = hana::unpack(get_array_fns, [](auto ...get_array) {
    return hana::tuple_t<decltype(get_array())...>;
  });

  BOOST_HANA_CONSTANT_CHECK(hana::equal(
    decltype(result_types){},
    hana::tuple_t<std::array<float,  0>,
                  std::array<float,  1>,
                  std::array<float,  2>,
                  std::array<float,  3>,
                  std::array<double, 0>,
                  std::array<double, 1>,
                  std::array<double, 2>,
                  std::array<double, 3>,
                  std::array<long,   0>,
                  std::array<long,   1>,
                  std::array<long,   2>,
                  std::array<long,   3>,
                  std::array<double, 0>,
                  std::array<double, 1>,
                  std::array<double, 2>,
                  std::array<double, 3>>));
}

【讨论】:

    【解决方案3】:

    如下(没有提升)呢?

    #include <array>
    #include <iostream>
    
    template <typename T, std::size_t Dim>
    constexpr std::array<T, Dim> get_array ()
     { return {}; }
    
    // fake test
    template <typename T, std::size_t Dim>
    constexpr bool checkArray (std::array<T, Dim> const &)
     { return true; }
    
    template <typename T, std::size_t ... Is>
    constexpr bool checkSequence (std::index_sequence<Is...> const &)
     { return (... && checkArray(get_array<T, Is>())); }
    
    template <typename ... Ts>
    constexpr bool checkTypes ()
     { return (... && checkSequence<Ts>(std::make_index_sequence<25u>{})); }
    
    int main ()
     {
       constexpr auto value = checkTypes<float, double, long double>();
    
       std::cout << value << std::endl;
     }
    

    【讨论】:

      猜你喜欢
      • 2013-12-16
      • 2011-07-01
      • 1970-01-01
      • 2013-04-29
      • 2017-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多