Reputation: 4351
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
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:
std::make_tuple
if you need values in the returned tuple,std::tie
if you need lvalue references in the returned tuple,std::forward_as_tuple
if you need to keep the types of references of the inputs to build the tuple.Upvotes: 3
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