4

I'm taking my first steps with Boost.Hana, so please bear with me. I have

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

#include <string>

struct A
{
  int integer;
  std::string string;
};

int main()
{
  auto tuple = hana::make_tuple(42, "42");
  A a;
  hana::for_each(hana::zip(hana::members(a), tuple), [](auto& element) { element[0_c] = element[1_c]; });
}

This is my attempt at assigning each tuple element to its respective (sequential) member of A. This does not work (see live example for complete error). It boils down to

main.cpp:19:54: note: candidate function [with $0 = boost::hana::tuple<int, int>] not viable: expects an l-value for 1st argument

 hana::for_each(hana::zip(hana::members(a), input), [](auto& element) { element[0_c] = element[1_c]; });
                                                    ^

I read in the documentation that Hana algorithms have by-value semantics, but then how would one go about doing this kind of thing? Is constructing an A from the hana::tuple the only thing possible?

rubenvb
  • 74,642
  • 33
  • 187
  • 332
  • That is what `Algorithms in Hana always return a new container holding the result.` would suggest... You are encouraged to use pure functions and create new objects over performing destructive updates on old ones. – user268396 Jan 16 '19 at 22:50
  • @user268396 what if I have a huge struct all filled in with complicated things, but I want to set a single member? Is that really impossible? In the mean time I discovered `hana::members(a) = input;` also "works" in the sense that it compiles, but again, the lhs is a copy of the members so `a` is never modified. – rubenvb Jan 16 '19 at 22:57

2 Answers2

4

To modify a Struct in place, use hana::accessors which provides a tuple of hana::pairs each with a key and an accessor function. Also since we don't have reflection yet you need to use one of the macros like BOOST_HANA_ADAPT_STRUCT to implement A as a hana::Struct .

The other answer addresses the lambda taking an rvalue because the zipped tuple is a temporary object.

#include <cassert>
#include <boost/hana.hpp>
namespace hana = boost::hana;
using namespace hana::literals;

#include <string>

struct A
{
  int integer;
  std::string string;
};
BOOST_HANA_ADAPT_STRUCT(A, integer, string);

int main()
{
  auto tuple = hana::make_tuple(42, "42");
  A a;
  hana::for_each(
    hana::zip(hana::accessors<A>(), tuple),
    [&a](auto&& element) {
      auto accessor_pair = hana::at_c<0>(element);
      auto get_member = hana::second(accessor_pair);
      get_member(a) = hana::at_c<1>(element);
    });

  assert(a.integer == 42 && a.string == "42");
}
Jason Rice
  • 1,686
  • 1
  • 12
  • 17
  • This seems to be it. I was trying to tie an accessors instance to `a`, but that's not how it works, the binding is done at the call site of the contained "getters". Thanks! – rubenvb Jan 17 '19 at 12:48
0

I'm not real familiar with Boost nor Hana; but I went to their website and read a little bit of their documentation on some of their objects, functions etc. I do not know if this will help you but I was able to modify your code slightly and I got this to compile:

int main() {
    A a;
    auto tuple = hana::make_basic_tuple( 42, "42" );

    hana::for_each( hana::zip( hana::members(a), tuple), 
                               [&](auto&& element) {
                                   hana::at( tuple, hana::size_c<0> );
                                   hana::at( tuple, hana::size_c<1> );
                               }
                  );

}

I changed your lambda to have [&] and changed the parameter to be an auto&& and I used hana::at(). AFAIK I do not think this is assigning anything at the moment but you might be able to use this and go from here, but the positive part is that on the same website your provided with your demo code and with the same compiler settings, this did compile without error. Live Demo

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 1
    This does not give me write access to `a` though, because of the by value semantics. I need accessors like@Jason suggested. – rubenvb Jan 17 '19 at 12:48