在 Boost.Hana 中是否存在与 Boost.Fusion 中的 View 概念等效的概念?

Is there an equivalent of View concept from Boost.Fusion in Boost.Hana?

我试图用 hana::for_each 迭代用户定义的结构并注意到它得到 copied/moved,而 Boost.Fusion 允许您就地迭代原始结构.

我没有在 Boost.Hana 中找到 Boost.Fusion 中的 View 概念。我如何将转换应用到没有每次都 copying/moving 的序列?

#include <boost/hana.hpp>
#include <iostream>

struct Foo {
    Foo() = default;
    Foo(const Foo&) { std::cout << "copy" << std::endl; }
    Foo(Foo&&) { std::cout << "move" << std::endl; }
};

struct Struct {
    BOOST_HANA_DEFINE_STRUCT(Struct,
        (Foo, foo)
    );
};

int main() {
    Struct s;
    auto m = boost::hana::members(s); // copy constructor invoked
}

更新:我尝试使用 hana::transformstd::ref 应用于成员,但是 Struct 不是 Functior,所以 transform 不是适用于这种情况。我能够使用 hana::accessors 实现所需的行为,但对我来说它看起来有点老套。我希望有一种创建视图的方法。

hana::for_each(hana::accessors<Struct>(), [&s](const auto& accessor) {
    const auto& member = hana::second(accessor)(s); // No copying
});

就视图而言,boost/hana/experimental/view.hpp 中有一些未记录的功能,因此它们肯定会出现在 Boost.Hana。

Struct 当前的问题是它在键值对上是 Foldable。在 hana::unpack 中,它会将结构中的每个值成对放置,创建一个副本。您使用 hana::accessors 的解决方案目前是 IMO 的方式。

请注意,目前有一个未解决的问题:https://github.com/boostorg/hana/issues/175

Jason 说的 Hana 中有对视图的实验支持是正确的。您遇到的问题很常见,Hana 目前没有以优雅的方式解决它。我希望向 Hana 添加视图可以通过为所有有意义的算法提供按值和按引用语义来解决这个问题。但是以连贯的方式添加它是非常重要的,因此该功能处于实验状态。

也就是说,您可以通过使用访问器(如您在问题中所示)或通过迭代与结构成员关联的键来解决您的问题:

#include <boost/hana.hpp>
#include <iostream>
namespace hana = boost::hana;

struct Foo {
    Foo() = default;
    Foo(const Foo&) { std::cout << "copy" << std::endl; }
    Foo(Foo&&) { std::cout << "move" << std::endl; }
};

struct Struct {
    BOOST_HANA_DEFINE_STRUCT(Struct,
        (Foo, foo)
    );
};

int main() {
    Struct s;
    hana::for_each(hana::keys(s), [&s](const auto& key) {
        const auto& member = hana::at_key(s, key); // No copying
    });
}

如果您想将成员本身作为一个序列来操作,但又不想复制它们,您可以创建一个引用序列,如下所示:

#include <boost/hana.hpp>
#include <iostream>
namespace hana = boost::hana;

struct Foo {
    Foo() = default;
    Foo(const Foo&) { std::cout << "copy" << std::endl; }
    Foo(Foo&&) { std::cout << "move" << std::endl; }
};

struct Struct {
    BOOST_HANA_DEFINE_STRUCT(Struct,
        (Foo, foo)
    );
};

int main() {
    Struct s;
    auto members = hana::transform(hana::keys(s), [&s](auto const& key) {
        return std::ref(hana::at_key(s, key));
    });
}

members 将是一系列 std::reference_wrapper,您可以随身携带,但访问它们时必须使用 .get()。在 Hana 的未来版本中,hana::members 可能会 return 一个 key/value 对的视图,其中值是对原始成员的引用。但是在这成为可能之前必须解决几个问题。

希望对您有所帮助!