Alexey Starinsky
Alexey Starinsky

Reputation: 4351

What is the difference between std::tie and std::forward_as_tuple

For a given class, if I want to write all the comparison operators, to avoid code duplication, I would write them something like this:

class B {
public:
    bool operator==(Type const& rhs) const {
        return as_tuple() == rhs.as_tuple();
    }

    bool operator!=(Type const& rhs) const {
        return as_tuple() != rhs.as_tuple();
    }

    // .. and same for other operators ..

private:
    auto as_tuple() const {
        return std::tie(a, b, c); // all the members
    }
};

I could implement as_tuple() there with std::tie() or I could implement it with std::forward_as_tuple(). Is there a difference? Which should I prefer?

Upvotes: 16

Views: 3253

Answers (2)

Prashant Nidgunde
Prashant Nidgunde

Reputation: 435

Here is a nice post on the same subject.

From the article in the link:

In summary, when you need to build a tuple, use:

  1. std::make_tuple if you need values in the returned tuple,
  2. std::tie if you need lvalue references in the returned tuple,
  3. std::forward_as_tuple if you need to keep the types of references of the inputs to build the tuple.

Upvotes: 3

Barry
Barry

Reputation: 304182

Let's just look at the signatures. std::tie() is:

template< class... Types >
constexpr tuple<Types&...> tie( Types&... args ) noexcept;

whereas std::forward_as_tuple() is:

template< class... Types >
constexpr tuple<Types&&...> forward_as_tuple( Types&&... args ) noexcept;

The only difference is that the former accepts only lvalues whereas the latter accepts lvalues and rvalues. If all of your inputs are lvalues, as they are in your use-case, they are exactly equivalent.

std::tie() is largely intended as the left-hand side of assignment (e.g. std::tie(a, b) = foo; to unpack a pair), whereas std::forward_as_tuple() is largely intended to pass things around in functions to avoid copies. But they can both be used to solve this problem. tie is obviously quite a bit shorter, and arguably more well-known (the cppreference example for tie uses it to implement operator<), so that would get my vote.

Upvotes: 10

Related Questions