User defined operator / Compile error

S

skywal_l

Hi,

I got a problem with this code:

// Starts here
#include <iostream>
#include <vector>

class A {};

std::vector<A> operator>>(A &a, const std::string &s)
{
std::vector<A> v;
v.push_back(a);
return v;
}

std::vector<A> operator>>(const std::string &s, A a)
{
std::vector<A> v;
v.push_back(a);
return v;
}

std::vector<A> &operator>>(A &a, std::vector<A> &v)
{
v.push_back(a);
return v;
}

std::vector<A> &operator>>(std::vector<A> &v, A a)
{
v.push_back(a);
return v;
}

std::vector<A> &operator>>(std::vector<A> &v, const std::string &s)
{
return v;
}

std::vector<A> &operator>>(const std::string &s, std::vector<A> &v)
{
return v;
}

int main(int, char **)
{
A a;
"titi" >> a >> "toto";
return 0;
}
// Ends here

This code would not compile with g++ 4.0.6 which fails this way:
:~/gcc$ g++ test.cpp
test.cpp: In function #int main(int, char**)#:
test.cpp:48: error: no match for `operator>>' in `operator>>(const
std::string&, A)((a, A())) >> "toto"'
test.cpp:6: note: candidates are: std::vector<A, std::allocator<A> >
operator>>(A&, const std::string&)
test.cpp:14: note: std::vector<A, std::allocator<A> >
operator>>(const std::string&, A)
test.cpp:22: note: std::vector<A, std::allocator<A> >&
operator>>(A&, std::vector<A, std::allocator<A> >&)
test.cpp:28: note: std::vector<A, std::allocator<A> >&
operator>>(std::vector<A, std::allocator<A> >&, A)
test.cpp:34: note: std::vector<A, std::allocator<A> >&
operator>>(std::vector<A, std::allocator<A> >&, const std::string&)
test.cpp:39: note: std::vector<A, std::allocator<A> >&
operator>>(const std::string&, std::vector<A, std::allocator<A> >&)


Any idea??
Thanks.
 
J

Joe Greer

int main(int, char **)
{
A a;
"titi" >> a >> "toto";
return 0;
}
// Ends here
Any idea??
Thanks.

A quoted string is a constant array, not a std::string and you don't
have an overload for that. Try:

std::string("titi") >> a >> std::string("toto")


At least you should find your overloaded functions.

joe
 
S

skywal_l

A quoted string is a constant array, not a std::string and you don't
have an overload for that. Try:

std::string("titi") >> a >> std::string("toto")

At least you should find your overloaded functions.

joe

No it doesn't help. And it compiles on msvc8 anyway...
Any more idea? Thanks again!

LS
 
R

Robert Bauck Hamar

Hi,

I got a problem with this code:

// Starts here
#include <iostream>
#include <vector>

class A {};

std::vector<A> operator>>(A &a, const std::string &s)
{
std::vector<A> v;
v.push_back(a);
return v;
}

std::vector<A> operator>>(const std::string &s, A a)
{
std::vector<A> v;
v.push_back(a);
return v;
}

std::vector<A> &operator>>(A &a, std::vector<A> &v)
{
v.push_back(a);
return v;
}

std::vector<A> &operator>>(std::vector<A> &v, A a)
{
v.push_back(a);
return v;
}

std::vector<A> &operator>>(std::vector<A> &v, const std::string &s)
{
return v;
}

std::vector<A> &operator>>(const std::string &s, std::vector<A> &v)
{
return v;
}

int main(int, char **)
{
A a;
"titi" >> a >> "toto";

"titi" >> a
should find
std::vector<A> operator >> (const std::string&, A)
Unfortunately, you have no operator >> which can take this vector as a first
parameter. The candidates taking a vector<A>& is not used because that
would be binding a temporary to a non-const reference.

To solve this, you could do:
std::vector<A> v("titi" >> a);
or redefine the operator you want:
std::vector<A> operator >> (const std::vector<A>& v, const std::string &s)
{
return v;
}
 
S

skywal_l

"titi" >> a
should find
std::vector<A> operator >> (const std::string&, A)
Unfortunately, you have no operator >> which can take this vector as a first
parameter. The candidates taking a vector<A>& is not used because that
would be binding a temporary to a non-const reference.

Oh yeah? Is this a C++ standard feature? Because it doesn't seem to be
any pb for msvc8... I think it's kind of restrictive, why prevent
temporary to be passed by reference?
To solve this, you could do:
std::vector<A> v("titi" >> a);
or redefine the operator you want:
std::vector<A> operator >> (const std::vector<A>& v, const std::string &s)
{
return v;

}

Ok, it's making the trick.
Thanks a lot for your explanation and solution!


LS
 
R

Robert Bauck Hamar


Yes, really.
Is this a C++ standard feature?

Yes. But it's worth to mention that a lot of pre standard compilers
supported binding of temporaries to non-const references.
Because it doesn't seem to be any pb for msvc8...

pb = problem? Perhaps not. A compiler might compile the complete works of
Shakespeare if it wants. It just has to emit a message whenever you make an
error that requires a diagnostic. So you should always check the messages
your compiler gives you.
I think it's kind of restrictive, why prevent temporary to be passed by
reference?

You can. The standard prevents temporaries to bind to non-constant
references. I believe this is prevented because it leads to hard-to-find
bugs.

However, there is a proposal to make it possible to create rvalue references
in the next version of the standard:
<URL:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html>.
<URL:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm>
gives some background.
 
F

Frank Birbacher

Hi!

You already got the response about binding temporaries to references.

Here is another advise that will at least make your code work.

std::vector<A> &operator>>(A &a, std::vector<A> &v)

{
v.push_back(a);
return v;
}

Apply this to the following, too:
std::vector<A> &operator>>(std::vector<A> &v, A a) [snip]
std::vector<A> &operator>>(std::vector<A> &v, const std::string &s) [snip]
std::vector<A> &operator>>(const std::string &s, std::vector<A> &v)


Now don't protest about performance, unless you can proof that your
program needs to be faster. There are means to get this faster, but they
require more programming experience than overloading operators. So I'll
not explain it until someone (maybe you) asks.

Frank
 
A

Alf P. Steinbach

* Frank Birbacher:
Hi!

You already got the response about binding temporaries to references.

Here is another advise that will at least make your code work.

That's Undefined Behavior, returning a reference to a local.

The OP's code doesn't provide clear cues as to what it's meant to
achieve (e.g. ignoring string arguments), except the general notion of
pushing A objects onto the end of a vector via operator>>.

I'd use operator<<,

std::vector<A>& operator<<( std::vector<A>& v, A const& a )
{
v.push_back( a );
return v;
}

Apply this to the following, too:
std::vector<A> &operator>>(std::vector<A> &v, A a) [snip]
std::vector<A> &operator>>(std::vector<A> &v, const std::string &s) [snip]
std::vector<A> &operator>>(const std::string &s, std::vector<A> &v)

No need: when you first have Undefined Behavior, it's Undefined Behavior
all over the place, and adding more doesn't improve things. :)

Cheers,

- Alf
 
F

Frank Birbacher

Hi!
* Frank Birbacher:

That's Undefined Behavior, returning a reference to a local.

Oops. I missed the reference in the return type. I meant to do full
copies in the return, too:

std::vector<A> operator >> (A &a, std::vector<A> v)
{
v.push_back(a);
return v;
}
The OP's code doesn't provide clear cues as to what it's meant to
achieve (e.g. ignoring string arguments), except the general notion of
pushing A objects onto the end of a vector via operator>>.

I'd use operator<<,

The use of the container is not apparent in his example. I guess it is
meant to be hidden anyway. So I could live with ">>" as meaning to
somehow "combine" things.

Frank
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top