开发者

C++ : cout with a terenary if-statement

I get this ERROR: "error: overloaded function with no contextual type information".

cout << (i % 5 == 0) ? endl : "";

Is what I am doing possible; am I just doing it wrong, or do I have to overload the << ope开发者_Go百科rator?


It won't work that way (even if you fix the the precedence error). You have two problems here, the second more severe than the first.

The first problem is that std::endl is a template. It is a function template. A template has to be specialized. In order to specialize that template the compiler has to know (to deduce) the template arguments. When you do

std::cout << std::endl;

the specific function pointer type expected by operator << is what the compiler uses to figure out how to specialize the std::endl template.

However in your example you essentially "detached" the std::endl from operator << by moving the std::endl into an ?: subexpression. Now the compiler has to compile this expression first

(i % 5 == 0) ? endl : ""

This expression cannot be compiled since the compiler does not know how to specialize the std::endl template. There's no way to deduce the template arguments without any context.

For example, this simple C++ program

#include <iostream>
int main() {
   std::endl;
}

will also fail to compile for the very same reason: without context the compiler does not know how to instantiate std::endl.

You can "help" the compiler to resolve the problem by specifying the template arguments explicitly

(i % 5 == 0) ? endl<char, char_traits<char> > : "";

This will explicitly tell compiler how to instantiate endl. The original error message you were getting will go away.

However, this will immediately reveal the second, more serious problem with that expression: specialized endl is a function (which decays to a function pointer in this context) while "" is a string literal. You cannot mix a function pointer and a string literal in a ?: operator like that. These types are incompatible. They cannot be used together as the 2nd and the 3rd operand of ternary ?:. The compiler will issue a different error message about this second problem.

So, basically, that latest problem you have here is as if you tried to do something like

cout << (i % 5 == 0 ? 10 : "Hi!");

This will not compile for the very same reason your expression will not compile.

So, the expression you are trying to write cannot be written that way. Rewrite it without trying to use the ?: operator.


As support, see the following transcript:

$ cat qq.cpp
#include <iostream>
using namespace std;
int main (void) {
    int i = 5;
    cout << ((i % 5 == 0) ? endl : "");
    return 0;
}

$ g++ -o qq qq.cpp
qq.cpp: In function 'int main()':
qq.cpp:5: error: overloaded function with no contextual type information


The two arguments to the ? operator must be of the same type (at least after potential promotions, implicit constructors, casting operators etc. kick in). std::endl is actually a function template (details below) which the stream then invokes to affect its state: it is not a string literal like "".

So, you can't do this exactly, but you can probably get the behaviour you actually want - consider whether...

expr ? "\n" : ""

...meets your needs - it is similar but doesn't flush the stream (IMHO, std::cout should generally be flushed as infrequently as possible - especially by low level library code - as that provides better performance). (It's also more flexible, e.g. expr ? "whatever\n" : "" / can't append endl to a string literal.)

E.g. for GCC 4.5.2, endl is:

template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }


  • The two alternatives of ?: must have the same type or one be convertible to the other.

  • endl is a template and the context doesn't give enough information for which to choose. So it hasn't even a type. (Thats is your error message).

  • As other already said, the binding isn't the one you expect.


It may well be possible (I doubt it myself). However, it's also silly, effectively as silly as:

cout << "";

What you should be doing in this case is a simple:

if (i % 5 == 0) cout << endl;

You shouldn't use ternary just for the sake of using it. Actually you shouldn't use any language feature just for the sake of using it. I don't write code like:

if (1) { doSomething(); }

just because I can. A simple doSomething(); is much better.


Try this, it works:

cout << ((i % 5 == 0) ? "\n" : "");


This is how it is supposed to look like to make it work correctly:

cout << ((i % 5 == 0) ? '\n' : " ");


Operator << has higher priority than ?:. Try this:

cout << ((i % 5 == 0) ? endl : "");
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜