c++ - 给定 boost::hana 中的键元组,如何从映射中获取值元组?

标签 c++ boost metaprogramming boost-hana

我知道我可以使用 operator[]boost::hana::map 获取单个值。但是我发现“向量化它”出奇地困难:从多个键的元组中获取多个值。

假设我们有一个 hana::map the_map:

#define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#include <boost/hana/string.hpp>
#include <boost/hana/map.hpp>
#include <string>
namespace hana = boost::hana;
using namespace hana::literals;

auto the_map = hana::make_map(
    hana::make_pair("key1"_s, std::string("value1")),
    hana::make_pair("key2"_s, int(42)),
    hana::make_pair("key3"_s, std::string("value3")),
    hana::make_pair("key4"_s, float(3.14)),
    hana::make_pair("key5"_s, std::string("value5"))
);

最后我想将这个映射的值解包到一个函数调用中。因为 C++ 按位置(而不是按名称)传递参数,所以我需要获取具有特定顺序的值的元组。 hana::map 不保证条目的顺序,所以我需要按键提取它们,有效地在命名元组的方向上实现一些东西,以实现类似于按名称传递函数参数的东西。

假设我有一个函数 myfun 和一个编译时键列表:

#include <boost/hana/tuple.hpp>

void myfun(std::string par1, int par2, std::string par3, float par4, std::string par5) {
    //...
}

constexpr auto the_keys = hana::make_tuple("key1"_s, "key2"_s, "key3"_s, "key4"_s, "key5"_s);

我想要的是在给定键 the_keys 的情况下以某种方式从 the_map 中获取值的元组,这样我就可以使用 int main() 调用该函数{hana::unpack(the_items, myfun);}.

到目前为止,我做的最好的是以下失败的 C++ 代码:

#include <boost/hana/at_key.hpp>
#include <boost/hana/fold_left.hpp>

template<typename T, typename U>
auto accessor(U sequence, T key) {
    static_assert(hana::Foldable<U>::value);
    return hana::insert(sequence, 0_c, ms[key]);
}

auto the_items_manually=accessor(accessor(accessor(hana::make_tuple(), "key1"_s), "key2"_s), "key3"_s); //this works
auto the_items = hana::fold_left(keys, hana::make_tuple(), accessor); //compile error

最后一行产生错误。

error: no match for call to ‘(const boost::hana::fold_left_t) (const boost::hana::tuple<boost::hana::string<'k', 'e', 'y', '1'>, boost::hana::string<'k', 'e', 'y', '2'>, boost::hana::string<'k', 'e', 'y', '3'>, boost::hana::string<'k', 'e', 'y', '4'>, boost::hana::string<'k', 'e', 'y', '5'> >&, boost::hana::tuple<>, <unresolved overloaded function type>)’
     auto the_items = hana::fold_left(keys, hana::make_tuple(), accessor);

我的 GCC 7.3.0 C++14 编译器还指出,

boost/hana/fold_left.hpp:26:30: note: candidate: template<class Xs, class State, class F> constexpr decltype(auto) boost::hana::fold_left_t::operator()(Xs&&, State&&, F&&) const
     constexpr decltype(auto) fold_left_t::operator()(Xs&& xs, State&& state, F&& f) const {
                              ^~~~~~~~~~~

boost/hana/fold_left.hpp:26:30: note:   template argument deduction/substitution failed:
/home/Adama-docs/Adam/MyDocs/praca/IMGW/repos/all5/eulag-verification/simple_test/test5.cpp:67:72: note:   couldn't deduce template parameter ‘F’
     auto the_items = hana::fold_left(keys, hana::make_tuple(), accessor);
                                                                        ^

我明白,这个错误要我明确地输入一个正确类型的东西作为模板参数。好吧,不管它是什么,Hana 可用性的重点是不必输入类型,所以我认为我需要采用不同的方法。有人可以帮助我吗?

最佳答案

这里给 hana::fold_left 的函数 accessor 必须是 lambda 或函数对象,否则我认为它会起作用。 (不支持函数指针)

为了更好的编译时性能,hana::unpack在可能的情况下优于 hana::fold_left,因为它不必为列表中的每个元素创建中间对象。

这是一个使用捕获 map 的高阶函数的示例:

#define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#include <boost/hana.hpp>
#include <string>
#include <iostream>

namespace hana = boost::hana;
using namespace hana::literals;

int main() {
  auto get_values = [](auto const& map) {
    return [&](auto const& ...key) {
      return hana::make_tuple(map[key]...);
    };
  };

  auto myfun = [](std::string par1, int par2, std::string par3, float par4, std::string par5) {
    std::cout << par1 << '\n'
              << par2 << '\n'
              << par3 << '\n'
              << par4 << '\n'
              << par5 << '\n'
              ;
  };

  auto the_map = hana::make_map(
    hana::make_pair("key1"_s, std::string("value1")),
    hana::make_pair("key2"_s, int(42)),
    hana::make_pair("key3"_s, std::string("value3")),
    hana::make_pair("key4"_s, float(3.14)),
    hana::make_pair("key5"_s, std::string("value5"))
  );

  constexpr auto the_keys = hana::make_tuple("key1"_s, "key2"_s, "key3"_s, "key4"_s, "key5"_s);

  auto values = hana::unpack(the_keys, get_values(the_map));
  hana::unpack(values, myfun);
}

您可能还想查看 Boost.Hof用于将原始函数 boost 为对象和其他简洁的无点编程内容的工具。

关于c++ - 给定 boost::hana 中的键元组,如何从映射中获取值元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51305106/

相关文章:

c++ - 类模板,在定义中引用它自己的类型

c++ - 限制函数在代码库中的使用次数

c++ - 如何在 C++ 中单独给定一个 ProgID 来实例化一个类?

c++ - cmake 找不到 qt 5.1.1

c++ - C++中具有输出限制的排列

java - 将代码从 java 转换为 c++ 的 mysql 连接器错误

c++ - 在 C++ 中使用模板的 2s 幂数组

c++ - 当函数返回由模板类型和另一个类型组成的类型时,模板参数推导

c++ - 在接收器端Boost Asio读取序列化的结构

c++ - 编译错误:boost::promise<T>::set_value(const T&) 不存在