boostorg / boostorg/pfr

Copy less tie_from_structure

Open
#115 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
1.5k
Forks
176
Avg merge
5d 21h
Merged PRs (30d)
1

Description

Hi all, thanks for great work.

The problem I have with tie_from_structure is that it calls copy assignments instead of move assignments.
I think I understand why it happens: you convert the structure on the rhs of operator= into tuple of refs, and then assign it to the tuple of refs on the lhs.

Have you ever been thinking about a way to convert the structure on the rhs into a tuple of values, not refs?
To be more specific, I want to create a tuple, somehow call std::move on each member of the structure , and then assign that tuple (which now will be a rval) to the tuple of refs on the lhs of the operator?
This way it should work same as for std::tie.

I'm not familiar enough with your library to implement like that, so for now I'm using a workaround where I put both lhs args and rhs structure as a single function parameters:

https://godbolt.org/z/ajrGMPMez

Edit:

Ok, so here is a working example of how I would like the tie_from_structure to behave:
```

template
void tie_from_structure_assign_next(T &&)
{
static_assert(N == boost::pfr::tuple_size_v, "Wrong number of elements in tie_from_structure.");
}

template
void tie_from_structure_assign_next(T &&t, A &a, Args &... args)
{
a = std::move(boost::pfr::get(t));
tie_from_structure_assign_next - sizeof...(Args), T>(std::forward(t), args...);
}

template
void tie_from_structure_assign_all(T &&t, A &a, Args &... args)
{
static_assert(boost::pfr::tuple_size_v == sizeof...(Args) + 1, "Wrong number of elements in tie_from_structure.");
a = std::move(boost::pfr::get<0>(t));
tie_from_structure_assign_next<1, T>(std::forward(t), args...);
}

template
void tie_from_structure_assign(T &&t, Tuple &tuple, std::index_sequence) {
tie_from_structure_assign_all(std::forward(t), std::get(tuple)...);
}

template
struct tie_from_structure_tuple : std::tuple
{
using base = std::tuple;
using base::base;

template
constexpr tie_from_structure_tuple &operator=(T &&t)
{
tie_from_structure_assign(std::forward(t), dynamic_cast(*this), std::make_index_sequence::value>());
return *this;
}
};

template
constexpr tie_from_structure_tuple tie_from_structure(Elements &... args) noexcept
{
return tie_from_structure_tuple(args...);
}
```

Same example on godbolt: https://godbolt.org/z/Yq9nqdYnW

With this implementation you call move assignment for all members of the structure.
What do you think about it? Would it be possible to add sth like this to your library?

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the existing tie_from_structure implementation and the two linked Compiler Explorer examples. Compare its current copy-assignment behavior with the requested move-assignment behavior, then check how the proposed tuple type fits the library's API. Done means structure members are move-assigned through tie_from_structure while existing tuple-like behavior remains valid.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.