Reputation: 30095
I'm reviewing HTTP Server 3 example on Boost's website. There is following code in connection class:
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
where parse
declared as
template <typename InputIterator>
boost::tuple<boost::tribool, InputIterator> parse(request& req, InputIterator begin, InputIterator end)
I believe the goal was to copy returned value of tribool
to local variable. But what is the point of doing it via temporary object (boost::tie
) if one could write something like
boost::tuple<boost::tribool, char*> result = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
// Our tribool is available via result.get<0>();
?
Upvotes: 1
Views: 306
Reputation: 82041
The benefit is not performance, it is practicality and readability: since you are not interested by the second object returned by parse
, there is no need for keeping it. It is better to ignore it entirely and only get the result you are effectively interested in, namely the tribool
. The following code, which uses result
, will be much clearer.
In fact, when a function returns multiple data, it is often useful (in terms of readability) to "split" it to get the individual elements separately. For instance, consider std::set<T>::insert
, which returns an iterator to the element as well as a boolean indicating whether it was newly inserted. Which of the following code do you find clearer:
std::set<int> s;
std::pair<std::set<int>::iterator, bool> res = s.insert(42);
if (res.second)
{
doSomething(res.first);
}
vs
std::set<int> s;
std::set<int>::iterator itInsertedElement;
bool isNewlyInserted;
tie(itInsertedElement, isNewlyInserted) = s.insert(42);
if (isNewlyInserted)
{
doSomething(itInsertedElement);
}
In my opinion, the latter is easier to read.
Upvotes: 10
Reputation: 2713
I think they use tie
mainly for convenience. If you don't need InputIterator
, just the tribool
value, why would you want to create named variable?
This:
boost::tribool result;
boost::tie(result, boost::tuples::ignore) = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
becomes this:
boost::tuple<boost::tribool, char*> results = request_parser_.parse(request_, buffer_.data(), buffer_.data() + bytes_transferred);
boost::tribool result = boost::get<0>(results); // or you can use boost::get<0>(results) everywhere you use it.
And you have on stack totally useless results
.
Temporary value returned from boost:tie
will be probably optimized by a compiler, so there shouldn't be any memory overhead.
Upvotes: 3
Reputation: 299770
It's only a semantic consideration I think.
.get<0>()
result
variable is only bound with the useful part, and no other variable is required.Performances here should not be affected as the compiler will treat it as:
boost::tuple<boost::tribool, char*> __tmp = request_parser_.parse(/**/);
boost::trilbool result;
boost::tie(result, boost::tuples::ignore) = __tmp;
and the optimizer will then take care of eliminating the cruft and reducing that as much as possible.
Upvotes: 3
Reputation: 171263
I doubt there's any measurable performance difference (certainly not compared to the IO cost) but it's more convenient to simply refer to result
rather than using get<0>()
to get it out of the tuple.
Upvotes: 0