C++ : cout with a terenary if-statement

user658096 picture user658096 · Apr 20, 2011 · Viewed 12.7k times · Source

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 << operator?

Answer

AnT picture AnT · Apr 20, 2011

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