Re: Multiple return values (was Re: Const Considerations)
James Kanze wrote:
Yechezkel Mett wrote:
template<class FwdIt, class Ty>
struct {
FwdIt lower_bound;
FwdIt upper_bound;
} equal_range(
FwdIt first,
FwdIt last,
const Ty& val)
{
FwdIt lower;
FwdIt upper;
... calculate lower and upper ...
return { lower, upper };
}
int main()
{
std::vector<int> v;
... fill v with ordered values ...
auto equal = equal_range(v.begin(), v.end(), 5)
std::cout << "lower = " << equal.lower_bound
<< ", upper = " << equal.upper_bound << std::endl;
}
What's the difference between this and the current return type
for equal_range (std::pair< Iter, Iter >)?
Currently, using std::pair for multiple returns is syntactically
unwieldy and limited to two values. With tr1::tuple the limit is
removed; with C++0x the syntax will be tidied. The remaining difference
is the ability to name the return values, which I feel is not insignificant.
Something along those lines will probably be legal. I don't
think the exact syntax has been finalized in either case.
N2122 says the auto proposal is already in the Working Paper and the
initializer list proposal is "Blessed by Evolution - Wording required
for Core review" so I'm not expecting much change.
(And
of course, there is no assignment in main---the auto only works
in declarations with initialization.)
Whoops.
Note that this is NOT multiple return values. To emulate
multiple return values in C++, you'd need some sort of tuple of
references, and write something like:
int a;
double b ;
tuple_ref( a, b ) = f( x ) ;
tr1::tie(a, b)
Perhaps it's not multiple return values as implemented in other
languages, but I think it provides pretty much all of what people expect.
Given such a framework, swap could be written:
tuple_ref( a, b ) = tuple( b, a ) ;
tr1::tie(a, b) = tr1::make_tuple(b, a);
But swap wouldn't be written like that in C++, because it makes more
copies than necessary. Perhaps
tie(a, b) = make_tuple(std::move(b), std::move(a));
Still makes more moves than necessary, which could be a problem for a
heavy type which doesn't have a cheap move.
In a language which supports multiple returns and assignments,
of course, you don't need the tuple nor the tuple_ref; you could
just write:
a, b := b, a ;
In C++0x I hope
tie(a, b) = {b, a};
will do the job.
I was afraid a would get overwritten before being read, but there's a
temporary tuple created there which avoids that. There are still more
copies than necessary, which can be mitigated by using std::move. I
suspect the languages in which a, b := b, a is a standard idiom also use
reference semantics as opposed to the value semantics in C++, so they
don't have that problem.
Yechezkel Mett
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]