While trying to optimize a library I wrote, I came across an issue that I cannot seem to solve.
Consider the wrapper struct below (simplified):
template <typename T>
struct MyPair {
T data;
// some other stuff here
};
Perfectly forwarding a bunch of MyPairs is not an issue. But if I try to forward its member variable data for example into a tuple (could be others as well), it does not perfectly forward it but rather calls the move constructor instead:
template <typename... Ts>
struct Tuple {
public:
template <typename... Pairs>
Tuple(Pairs&&... pairs)
: data_{std::forward<Ts>(pairs.data)...} {} // Not forwarding, calling move instead
private:
std::tuple<Ts...> data_;
};
The full working example can be found here. The output indicates that a move constructor is called for each pair we will add.
I have tried other approaches such as forwarding the pair itself before accessing the member [1]. I have also tried alternatives but to no avail [2].
I would appreciate any help that allows us to get rid of unnecessary moves operations.
std::forward<Pairs>(pairs).dataand watch the magic happen. Member access respects value category too (not by chance, it was designed with forwarding in mind).data, I do not need any move at all. The value is perfectly forward with zero additional costs. The moment I decide to not store the whole Pair but just its valuedata, the compiler adds an additional move