C++ : cout with a terenary if-statement - c++

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?

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 : "");

Related

C++ - Unable to call inline std::cerr inside of a ternary operator

I'm trying to make a very simple setter method that checks if the start value isn't higher than the end value before setting it.
This is the basic code:
if (start <= this->end) {
this->start = start;
} else {
cerr << "Start cannot be higher than end." << endl;
}
I tried simplifying the method by using an inline if statement like so:
(start <= this->end) ? (this->start = start) : (cerr << "Start cannot be higher than end." << endl);
But IntelliSense tells me the following issue: function "std::basic_ostream<_Elem, _Traits>::basic_ostream(const std::basic_ostream<_Elem, _Traits> &) [with _Elem=char, _Traits=std::char_traits<char>]" cannot be referenced -- it is a deleted function
Uhh, I'm a bit confused as to what "deleted function" has to do with turning a simple if statement into an inline one. Could use some help. Thanks!
A ternary conditional expression a ? b : c is an expression and is therefore not equivalent to if (a) { b } else { c }.
Because it's an expression, it must have a type (and, if that type is not void, it has a value too). This is why you can put a ternary conditional on the right-hand side of an assignment (or even the left-hand side in some cases).
The type of a conditional expression is determined from the types of its second and third operands. If they have the same type, then the result is that type. If there is not some "unambiguous" type that both operand types can be converted to, then the ternary expression does not default to a void results; it instead results in a compilation error.
In your case, the two operands are:
(this->start = start)
(cerr << "Start cannot be higher than end." << endl)
The former has, I assume, some numeric type (the type of this->start) while the latter has std::ostream& type. There is no canonical "common type" of these two types, or in other words, the ternary operator has no "obvious" result type and a compilation error occurs.
An if statement would solve this problem. If you insist on using a conditional operator, you can do so like this:
(start <= this->end)
? void(this->start = start)
: void(cerr << "Start cannot be higher than end." << endl);
Here, both the second and third expressions are cast to void and the entire ternary expression therefore has result type void.
Note that you can't have something like break or return as one of the operands. condition ? void(return foo) : void(return bar) will not work, because return <expr> is a statement, not an expression. It has no type, not even void. In this case, you can only use an if statement. However, you can throw inside a conditional expression since throw <expr> is an expression.
The type of the statement for true case and false case must be matched.
Try this with , this->start (comma operator, then this->start) is added to the false case to match type:
(start <= this->end) ? (this->start = start) : (cerr << "Start cannot be higher than end." << endl, this->start);
By the way, my suggestion is you should simply write if statement in one line instead of using conditional operator like this if you want things in one line:
if (start <= this->end) this->start = start; else cerr << "Start cannot be higher than end." << endl;

printing out unordered map values prints out address [duplicate]

Why is the output of the below program what it is?
#include <iostream>
using namespace std;
int main(){
cout << "2+3 = " <<
cout << 2 + 3 << endl;
}
produces
2+3 = 15
instead of the expected
2+3 = 5
This question has already gone multiple close/reopen cycles.
Before voting to close, please consider this meta discussion about this issue.
Whether intentionally or by accident, you have << at the end of the first output line, where you probably meant ;. So you essentially have
cout << "2+3 = "; // this, of course, prints "2+3 = "
cout << cout; // this prints "1"
cout << 2 + 3; // this prints "5"
cout << endl; // this finishes the line
So the question boils down to this: why does cout << cout; print "1"?
This turns out to be, perhaps surprisingly, subtle. std::cout, via its base class std::basic_ios, provides a certain type conversion operator that is intended to be used in boolean context, as in
while (cout) { PrintSomething(cout); }
This is a pretty poor example, as it's difficult to get output to fail - but std::basic_ios is actually a base class for both input and output streams, and for input it makes much more sense:
int value;
while (cin >> value) { DoSomethingWith(value); }
(gets out of the loop at end of stream, or when stream characters do not form a valid integer).
Now, the exact definition of this conversion operator has changed between C++03 and C++11 versions of the standard. In older versions, it was operator void*() const; (typically implemented as return fail() ? NULL : this;), while in newer it's explicit operator bool() const; (typically implemented simply as return !fail();). Both declarations work fine in a boolean context, but behave differently when (mis)used outside of such context.
In particular, under C++03 rules, cout << cout would be interpreted as cout << cout.operator void*() and print some address. Under C++11 rules, cout << cout should not compile at all, as the operator is declared explicit and thus cannot participate in implicit conversions. That was in fact the primary motivation for the change - preventing nonsensical code from compiling. A compiler that conforms to either standard would not produce a program that prints "1".
Apparently, certain C++ implementations allow mixing and matching the compiler and the library in such a way that produces non-conforming outcome (quoting #StephanLechner: "I found a setting in xcode which produces 1, and another setting that yields an address: Language dialect c++98 combined with "Standard library libc++ (LLVM standard library with c++11 support)" yields 1, whereas c++98 combined with libstdc (gnu c++ standard library) yields an address;"). You can have a C++03-style compiler that doesn't understand explicit conversion operators (which are new in C++11) combined with a C++11-style library that defines the conversion as operator bool(). With such a mix, it becomes possible for cout << cout to be interpreted as cout << cout.operator bool(), which in turn is simply cout << true and prints "1".
As Igor says, you get this with a C++11 library, where std::basic_ios has the operator bool instead of the operator void*, but somehow isn't declared (or treated as) explicit. See here for the correct declaration.
For example, a conforming C++11 compiler will give the same result with
#include <iostream>
using namespace std;
int main() {
cout << "2+3 = " <<
static_cast<bool>(cout) << 2 + 3 << endl;
}
but in your case, the static_cast<bool> is being (wrongly) allowed as an implicit conversion.
Edit:
Since this isn't usual or expected behaviour, it might be useful to know your platform, compiler version, etc.
Edit 2: For reference, the code would usually be written either as
cout << "2+3 = "
<< 2 + 3 << endl;
or as
cout << "2+3 = ";
cout << 2 + 3 << endl;
and it's mixing the two styles together that exposed the bug.
The reason for the unexpected output is a typo. You probably meant
cout << "2+3 = "
<< 2 + 3 << endl;
If we ignore the strings that have the expected output, we are left with:
cout << cout;
Since C++11, this is ill-formed. std::cout is not implicitly convertible to anything that std::basic_ostream<char>::operator<< (or a non member overload) would accept. Therefore a standards conforming compiler must at least warn you for doing this. My compiler refused to compile your program.
std::cout would be convertible to bool, and the bool overload of the stream input operator would have the observed output of 1. However, that overload is explicit, so it shouldn't allow an implicit conversion. It appears that your compiler/standard library implementation doesn't strictly conform to the standard.
In a pre-C++11 standard, this is well formed. Back then std::cout had an implicit conversion operator to void* which has a stream input operator overload. The output for that would however be different. it would print the memory address of the std::cout object.
The posted code should not compile for any C++11 (or later conformant compiler), but it should compile without even a warning on pre C++11 implementations.
The difference is that C++11 made the convertion of a stream to a bool explicit:
C.2.15 Clause 27: Input/output library [diff.cpp03.input.output]
27.7.2.1.3, 27.7.3.4, 27.5.5.4
Change: Specify use of explicit in existing boolean conversion operators
Rationale: Clarify intentions, avoid workarounds.
Effect on original feature: Valid C++ 2003 code that relies on implicit boolean conversions will fail to
compile with this International Standard. Such conversions occur in the following conditions:
passing a value to a function that takes an argument of type bool;...
ostream operator << is defined with a bool parameter. As a conversion to bool existed (and was not explicit) is pre-C++11, cout << cout was translated to cout << true which yields 1.
And according to C.2.15, this should not longer compile starting with C++11.
You can easily debug your code this way. When you use cout your output is buffered so you can analyse it like this:
Imagine first occurence of cout represents the buffer and operator << represents appending to the end of the buffer. Result of operator << is output stream, in your case cout. You start from:
cout << "2+3 = " << cout << 2 + 3 << endl;
After applying the above stated rules you get a set of actions like this:
buffer.append("2+3 = ").append(cout).append(2 + 3).append(endl);
As I said before the result of buffer.append() is buffer. At the begining your buffer is empty and you have the following statement to process:
statement: buffer.append("2+3 = ").append(cout).append(2 + 3).append(endl);
buffer: empty
First you have buffer.append("2+3 = ") which puts the given string directly into the buffer and becomes buffer. Now your state looks like this:
statement: buffer.append(cout).append(2 + 3).append(endl);
buffer: 2+3 =
After that you continue to analyze your statement and you come across cout as argument to append to the end of buffer. The cout is treated as 1 so you will append 1 to the end of your buffer. Now you are in this state:
statement: buffer.append(2 + 3).append(endl);
buffer: 2+3 = 1
Next thing you have in buffer is 2 + 3 and since addition has higher precedence than output operator you will first add these two numbers and then you will put the result in buffer. After that you get:
statement: buffer.append(endl);
buffer: 2+3 = 15
Finally you add value of endl to the end of the buffer and you have:
statement:
buffer: 2+3 = 15\n
After this process the characters from the buffer are printed from the buffer to standard output one by one. So the result of your code is 2+3 = 15. If you look at this you get additional 1 from cout you tried to print. By removing << cout from your statement you will get the desired output.

c++ template: intiantiating a variable out of a particular integer (as type)

I've obviously misunderstood the code. Thanks for pointing out the error.
--original post--
I know for a while that integers can be used as types in c++ template programming. What surprises me is that when an integer such as 2 and 3 is used as a type, one can actually instantiate a variable out of the type, as shown in the example below extracted from gcc 4.8.1 random.h.
It seems to me that one can declare a variable
2 x; //not actual c++ code
and x will be an integer variable initialized to the value of 2.
Code for deterniming whether a number is a power of 2:
#include <iostream>
template<typename _Tp> inline bool
_Power_of_2(_Tp __x) {
return ((__x - 1) & __x) == 0;
};
int main() {
std::cout << _Power_of_2(2) << std::endl;
std::cout << _Power_of_2(3) << std::endl;
}
Output:
1
0
Can someone please explain what's going on here in terms of types and domains?
Are there any similar features in other programming languages that can do the same, i.e. using a concrete value as a type?
Also, is this feature available for other types, such as struct, string or float?
Thanks,
In your example, 2 is not used as a type, but as a function parameter. From that, the template parameter _tP is automatically deduced as int. So the lines inside main would be equivalent to:
std::cout << _Power_of_2<int>(2) << std::endl;
std::cout << _Power_of_2<int>(3) << std::endl;

Why is the template trying to instanciate with 'int&' instead of 'int'?

I am trying to write a simple function that will get me a number from user input within a range.
When instanciating this function i explicitly tell it i want it instanciated with int but still i get the error:
thermo.cpp:105:31: error: no matching function for call to ‘getInput(int&)’
Why is is trying to find a function that takes int& as argument?
template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max>
T getInput(T default_value = T()){
std::string input;
T myNumber = T(); //default inits
while(true){
getline(cin, input);
if(input.length() == 0){
return default_value;
}
// This code converts from string to number safely.
stringstream myStream(input);
if (myStream >> myNumber){
if(myNumber > max || myNumber < min){
stringstream ss;
ss << "Input out of bounds. Received " << myNumber << " expected between " << min << " and " << max << ".";
throw invalid_argument(ss.str());
}
return myNumber;
}
cout << "Invalid number, please try again" << endl;
}
}
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0>(param); // i specifically tell it i want 'int', why am i getting 'int&'?
}
Update
If i try CharlesB suggestion:
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0>(int(param));
}
i get
thermo.cpp:105:36: error: no matching function for call to ‘getInput(int)’
Forgot:
g++ 4.5.3 under cygwin
Command line:
$ g++ thermo.cpp -o thermo.exe -Wall -pedantic -std=c++0x
Update 2
if i call it like this
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0,15>(int(param)); // fully parameterized
}
it works... but i'd rather not specify an upper bound (not even numeric_limits) on each call.
Don't use templates for min and max:
template<class T>
T getInput(T default_value = T(), T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max());
There is no reason to use templates for those arguments(besides the fact that it does not work).
Edit: You can't use those arguments as template values since std::numeric_limits<T>::min() is a function, its value is known on runtime, and template value arguments have to be bound to a value at compile time. This is valid:
template<class T, T min = 0, T max = 5>
T getInput(T default_value);
Since 0 and 5 are known during compilation.
I don't know if this is the issue, but I can't imagine it's helping. This line:
template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max>
...is using min/max as values, when they're really functions. Maybe that's confusing the template parameters?
The error code does not mean what you think. The error code is a shorthand for:
no matching function call to getInput that takes an int modifiable lvalue expression as the single argument
Where int modifiable lvalue expression is the type of the expression that you are using to make the call in this case param. Now the problem is that output of error codes in this format is that it is very verbose and it would become very hard to read with just two or three arguments of non trivial types, so the compiler condenses the error report and tells you:
no matching function call to getInput(int&), note that here int& is not the type of the function that will be called, as the compiler was unable to find such a function, but rather it is the type of the argument that is being used in the call.
If you perform the change that CharlesB suggests, then you will get a different error message saying that it cannot find getInput(int). The difference here is that int(param) creates a temporary (rvalue expression), so the error now reflects it. The need for a different error code comes from the fact that if you had a getInput(int&) function, in this second case, that overload cannot be used.
On the reason why you are getting that error code the basic problem is that std::numeric_limits<T>::max is not of type T. Your problem is the very base of SFINAE: You have defined a template that takes as second and third arguments T, and that T should be initialized with std::numeric_limits<T>::min (and max). Now when the compiler tries to determine the function to call, it will find that template, use T for int (you provided the exact type), 0 for the min and will then try to infer the last argument. At this point it will try to get a T value (last template argument) through the default template argument by substituting the known template arguments in: std::numeric_limits<T>::max. The problem is that std::numeric_limits<int>::max is not an int, but rather a static member function, so the types don't match, yielding a substitution failure. The language determins that substitution failure is not an error (SFINAE) and it only means that this template will be removed from the list of candidates for the function call. Because there is no other matching overload, the compiler gives up and tells you that it could not find a matching function for the call.
In C++11 you can use std::numeric_limits<T>::max(), as the function is marked as a const_expr and can thus be called to obtain a constant expression of type T that can be used as the template argument, but if you are working with a C++03 compiler, you will need to work around the problem in a different way, like moving the min and max to default arguments to a function, or providing different overloads that take values from the user or will call a function (default to std::numeric_limist<T>::max if the argument is not present, but this latter option is more cumbersome.
Template functions are instanciated with argument type, and param is a int&.
Rather do
param = getInput(int(param));
Also min and max can't be template arguments, a template argument is class, a typename or a POD.

template function error: no operator found which takes a right hand operand of type

Hey! check out the following example.. its almost a copy paste from some cpp book.
i can't understand why is doesn't compile (under windows).
it says:
'<<' : no operator found which takes a right-hand operand of type 'div_t' (or there is no acceptable conversion)
this is the example:
#include <iostream>
template <class T>
T div(T a, T b) {
T result = a/b;
return result;
}
int main() {
int a = 5;
int b = 3;
std::cout << "INT " << div(a,b) << std::endl; //this line output the error
return 0;
}
thanks!!
div is a standard library function that returns a value of div_t type. When you included <iostream>, you apparently also indirectly included the declaration of the standard div. This is what the compiler is trying to use, not your template version.
This is probably the fault of the implementation, not your fault (assuming that the code you posted is the exact code you are trying to compile). If they include that portion of standard library in <iostream>, they probably should have done it in such a way that standard div would have become std::div. If they did it that way, you wouldn't have this problem.
You can do
std::cout << "INT " << div<>(a,b) << std::endl;
to explicitly ask the compiler to use your template.