My knowledge of C++ is small as I have only taken a couple classes. I undersand the basic case of using a friend function to overload the input, output stream operator for the "simple book example" of a Point object that has x, y instance variables. I am looking at a real project now, trying to understand what someone wrote and am getting the error:
error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
1> c:\program files\microsoft visual studio 9.0\vc\include\istream(1000): could be 'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,signed char *)' [found using argument-dependent lookup]
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
Noob question (1), can someone explain what basic_istream is? The error points to:
template<class _Traits> inline
basic_istream<char, _Traits>& __CLRCALL_OR_CDECL operator>>(
basic_istream<char, _Traits>& _Istr, signed char *_Str)
{ // extract a signed char NTBS
return (_Istr >> (char *)_Str);
}
The other part the error points to is:
void input(std::istream &in = std::ci开发者_StackOverflow社区n)
{in >> "(" >> X >> "," >> Y >> "," >> Z >> ")" ; }
inline friend std::istream& operator >> (std::istream& in, Coord &val)
{val.input(in); return in; };
Not sure what the error is looking at with my limited knowledge. It seems to be complaining about not the right type in the inline friend std::istream& operator>> function because of something wrong in the basic_istream template (which I'm not sure what is happening there). Any advice would be greatly appreciated. Thanks!
I'm pretty sure you can't parametrize istream extraction like that. It would be cool to be proven wrong though :)
Try this:
void input(std::istream &in = std::cin)
{
char t;
in >> t >> X >> t >> Y >> t >> Z >> t;
}
You can't use a string as an input in that way. You will need to use something like
char c;
cin.get() >> c;
if (c != '(') throw SomeError;
cin >> X;
cin.get() >> c;
if (c != ',') throw SomeError;
cin >> Y;
and so on.
First off, since you are new to C++: Do not trust the compiler error messages too much. In complicated code (templates, overloading...) you frequently get messages that are unrelated to the real issue.
Incorporating the comment on my answer: In your case though, the "," and similar objects are const, and the operator for the X, Y, Z is only declared on non-const objects, therefore not applicable. You'd either have to duplicate it, or only write a const version.
basic_istream
is the real class behind istream
-- the definitions look something like:
namespace std {
typedef basic_istream<char> istream;
typedef basic_ostream<char> istream;
typedef basic_istream<wchar_t> wistream;
typedef basic_ostream<wchar_t> wostream;
}
As to why you're getting the error message in the first place, the problem is pretty clearly with parts like:
some_istream >> "(";
You seem to want to read a character, and have it match that against an opening parenthesis, and (probably) fail if that's not what it finds. For better or worse, however, istream
s don't really support that directly. To do it, you could do something like this:
char ch;
some_istream >> ch;
if (ch != '(')
// handle failure
Alternatively, you could just read a character, and assume it's what should be there without checking. This can also allow somewhat more flexible input formatting, so "1 2 3" would be accepted just as well as "(1, 2, 3)". For some cases (e.g., input entered directly by a person) that can be fairly helpful. In other cases (e.g., input from another program) any deviation in the input signals a problem.
The problem is this:
in >> "("
Conceptually, this makes no sense. You're trying to read input into a string literal. (That's like trying to read input into the constant 5
.) The error is because a string literal is a const array of characters (hence the const char[2]
type) and so cannot be read into.
You might want this:
void input(std::istream &in = std::cin)
{
char dummy = 0;
in >> dummy >> X >> dummy >> Y >> dummy >> Z >> dummy;
}
All this does is read those characters into a dummy variable. It works, but those characters could be anything.
Rather, you should probably do the following:
// if you do it more than once, make it a function
bool expect_char(std::istream& in, char expected)
{
char check = 0;
in >> check;
if (check != expected)
{
in.putback(); // replace it
in.clear(std::ios::failbit); // set fail bit
return false;
}
else
{
return true;
}
}
void input(std::istream &in = std::cin)
{
if (!in) // if stream is bad, just return
return;
if (!expect_char(in, '('))
return;
in >> X;
if (!expect_char(in, ','))
return;
in >> Y;
if (!expect_char(in, ','))
return;
in >> Z;
if (!expect_char(in, ')'))
return;
}
Now the only problem is that if extraction fails half-way, we have modified the point object. Ideally, it would be all or nothing. We store intermediate values, then copy them when it all works:
void input(std::istream &in = std::cin)
{
if (!in)
return;
if (!expect_char(in, '('))
return;
int newX; // or whatever type it is
in >> newX;
if (!expect_char(in, ','))
return;
int newY;
in >> newY;
if (!expect_char(in, ','))
return;
int newZ;
in >> newZ;
if (!expect_char(in, ')'))
return;
X = newX;
Y = newY;
Z = newZ;
}
And we get what we were after.
精彩评论