views:

122

answers:

5

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::cin)
    {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!

+1  A: 

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.

Kdansky
String literals are const, so yes, the "(", ")", and the "," are const.
JoshD
In this case it is directly related to the real issue: no `operator>>` takes a stream on the left and `const char[2]` on the right.
Cubbi
+1  A: 

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;
}
genpfault
This doesn't enforce proper formatting, though.
GMan
+1  A: 

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.

TokenMacGuy
You usually don't want stream operations to throw.
GMan
A: 

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, istreams 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.

Jerry Coffin
A: 

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.

GMan
Mhmm. I'm sure I posted a class reading a special character from an istream here just the other day, but now I can't find it. (Searching SO really sucks. No full-text search capabilities except google, and that doesn't allow a data range.)
sbi