Why does ostream::operator<< allow ostringstream arg? [duplicate] - c++

Why can one cast a std::ostream to a void pointer? I am not aware of any such conversion operator in std::ostream. Code below
#include <iostream>
int main()
{
void *p = std::cout; // why does this work?
}
I'm asking this question since I've seen a placement operator new invoked as
Foo* pFoo = new (std::cerr) Foo;
and have absolutely no idea why would one write such a thing.
PS: I am compiling with g++ 4.9.2 with or without -std=c++11. clang++ does not accept the code.
PSS: Found out that due to the so called "safe bool problem" (see #nicebyte's answer), in pre C++11 a void* conversion operator was defined for std::ostream, which was then removed in C++11. However, my code compiles fine in C++11 using g++. More than that, clang++ rejects it no matter what version of the standard I use, even with -std=c++98, although my understanding is that it should accept if compiled as pre-C++11.

Read this (your question is answered in the very last section, "The safe bool problem").
To elaborate a bit, the implementation defines an implicit conversion to void* defined for things like std::cin and std::cout, just so that code like while(std::cin>>x){...} compiles, while code like int x = std::cin; doesn't. It's still problematic because you can write stuff like in your example.
C++11 solves this problem by introducing explicit conversions.
An explicit conversion operator looks like this:
struct A {
explicit operator B() { ... } // explicit conversion to B
};
When A has an explicit conversion to B, code like this becomes legal:
A a;
B b(a);
However, code like this is not:
A a;
B b = a;
A construct like if(std::cin) requires cin to be converted to bool, the standard states that in order for the conversion to be valid in that particular case, code like bool x(std::cin); should be "legal". Which can be achieved by adding an explicit conversion to bool. It allows cin/cout to be used in the above context, while avoiding things like int x = std::cout;.
For more information, refer to Bjarne's page as well as this question.

Answering only the follow-up, since nicebyte's answer is perfect for the original question.
Chances are, your gcc is set up to use libstdc++ (which hasn't changed the operator yet due it being an ABI-breaking change), and your clang is set up to use libc++ (which was from the beginning intended as a C++11 standard library and isn't quite conformant in C++98 mode - it provides a bool conversion operator that is explicit in C++11).

I think it's to allow for if (std::cout) ... without allowing for implicit conversion to bool, or something like that.

Related

Can't initialize std::function with comparator

In my C++ class we are learning to use function objects and the like, but now we got a code snippet that works on teacher's compiler but not on ours (we use different OS's).
We tested the code snippet below with several compilers (MSVC, clang) and they all reject it, a bit minimized:
#include <functional>
struct Fraction {
Fraction();
Fraction(int z, int n);
Fraction(Fraction&);
// various data members
};
struct FractionComparator {
int operator()(Fraction a, Fraction b) {
return 1;
}
};
int main() {
std::function<int(Fraction, Fraction)> comparator = FractionComparator();
}
We get on clang on macOS:
No viable conversion from 'FractionComparator' to 'function<int (Fraction, Fraction)>'
We already found out that adding a move constructor solves the problem, but we have no idea why this difference exists and why this code doesn't compile on our compilers.
Any ideas?
Why does adding a move-constructor solve the problem?
Fraction is attempted to be copy-constructed from an rvalue.
But constuctor Fraction(Fraction&); takes a non-constant reference. Non-const references are not allowed to bind to temporaries.
The proper constructor signature should be:
Fraction(const Fraction&);
When you declare a move constructor compiler will move-construct Fraction from an rvalue instead.
Why doesn't this code compile on our compilers, but compiles on the teacher's?
This code compiles with VC++.
It looks like the compiler is not conforming to the standard here.
I could find this StackOverflow question with some more detail. It seems to be a compiler extension that allows this to compile.
If compiler extensions are disabled via /Za flag it will not compile anymore.
Starting from C++14 the constructor you are trying to use does not participate in overload resolution unless the target function is callable with the given set of arguments (with std::declval<>() arguments of given types). In your case that would be std::declval<Fraction>() arguments.
Your FractionComparator functor is not callable with std::declval<Fraction>() arguments since it receives its arguments by value, while temporary objects of type Fraction cannot be copied: Fraction's copy-constructor's argument is declared as a non-const reference.
Declare your copy constructor as
Fraction(const Fraction &);
and the code will compile. If you have a good reason to keep it as non-const, then you will have to explore other opportunities for making this work. Why does your FractionComparator insist on receiving its parameters by value anyway?
Your question is tagged C++11, but apparently your compiler is retroactively implementing this C++14 requirement even in C++11 mode.

Why does unary operator & not require a complete type?

The following code compiles fine with both gcc 7.2.0 and clang 6.0.0.
#include <iostream>
struct stru;
void func(stru& s) {
std::cout << &s << std::endl;
}
int main() {
}
I'm wondering how this is OK. What if stru has overloaded operator&()? The compiler should not be able to tell with simply a forward declaration like struct stru. In my opinion, only std::addressof(s) is OK with an incomplete type.
What if stru has overloaded operator&()?
Then it is unspecified whether the overload will be called (See Oliv's comment for standard quote).
How could unary operator & does not require a complete type?
That's how the standard has defined the language. The built-in address-of operator doesn't need to know the definition of the type, since that has no effect on where to get the address of the object.
One consideration for why it is a good thing: Compatibility with C.

C++11 vs C++98 conversion operator behavior changes?

I'm looking to use some c++11 features in some existing c++ projects, so I started changing compile flags in Clang for some projects, and I keep running into a specific issue regarding C++11's treatment of conversion operators (or cast operators) that I didn't expect to see and don't understand why this is now considered an error when it's been valid C++ code that's not c++11
I've boiled it down to this simple example:
#include <iostream>
#include <vector>
class SerializableFormat
{
public:
size_t i;
};
class A
{
public:
size_t x, y;
A(size_t n) : x(n), y(1) { }
operator const SerializableFormat() const
{
SerializableFormat result;
result.i = x;
if (y)
{
result.i /= y;
}
return result;
}
};
int main(int argc, const char * argv[])
{
std::vector<SerializableFormat> v;
for(size_t i = 0; i < 20; i++)
{
v.push_back(A(i));
}
return 0;
}
If Clang's compilation flags are set to -std=c++98 and libstdc++, there are no issues and this compiles fine.
If Clang's compilation flags are set to -std=c++11 and libc++, I get the error No viable conversion from 'A' to 'value_type' (aka 'SerializableFormat')
Just to make it clear-- in case you're thinking about giving SerializableFormat a constructor just for the class A:
Since the SerializableFormat class is more suited for conversion to and from various classes, it makes sense for A (and other classes that wish to be serializable) to have constructors and conversion operators rather than expect SerializableFormat to cover every type of class that wants to be serializable, so modifying SerializableFormat to have a special constructor is not a solution.
Can anyone see what I'm doing wrong here?
As the comments correctly note, you can get compiling by dropping the const in the return type of your SerializableFormat conversion operator:
operator const SerializableFormat() const
As to whether clang is correct in this behavior is a matter of some dispute. The issue is being tracked by clang bug report 16682. At this time there is talk of creating a CWG (C++ committee) issue report, but that has not yet been done. I note that this bug report has been open for some time now (2013-07-23), but was updated as recently as 2015-01-28.
In the meantime, practical advice is just never to return by const-value. This was decent advice for C++98/03, but with move semantics becomes bad advice because it will disable move semantics.

Emulating explicit cast in C++03

I'm working on a legacy library that needs to be backwards compatible with C++03, but is also forward compatible to take advantage of C++11 features like move semantics and explicit casting.
So, is it possible to emulate explicit casting in C++03? I know obviously about the explicit bool (or "safe" bool) idiom - but that's only for casting to a boolean type. Is it possible to emulate a general explicit cast operator in C++03?
I checked around, and found a discussion about this in a book called "Imperfect C++ : Practical Solutions for Real-Life Programming".
In this book, they discuss some ideas about emulating an explicit cast in C++03 (the book was written before C++11). Ultimately, they recommend creating an explicit_cast<T> template. However, I don't like that solution because I want users to simply be able to use static_cast<T>, which works fine in C++11.
So, another solution was to force the compiler to do two conversions, which will disallow implicit conversions. An example of that would be something like:
class int_cast
{
public:
int_cast(const int& v) : m_value(v)
{ }
operator int() const
{
return m_value;
}
private:
int m_value;
};
struct Foo
{
Foo()
{
x = 10;
}
operator int_cast() const
{
return int_cast(x);
}
int x;
};
Here, a Foo should be explicitly convertible to int, but not implicitly. (This code is lifted almost verbatim from Imperfect C++, except in their example they are converting a custom Time object to a std::tm.
However, this doesn't actually work, at least not using GCC 4.7.2:
Foo f;
int x = static_cast<int>(f);
This results in :
test3.cpp: In function ‘int main()’:
test3.cpp:44:28: error: invalid static_cast from type ‘Foo’ to type ‘int’
So I guess "Imperfect C++" is wrong here. The compiler wasn't able to convert a Foo to an int, even with an explicit cast. (Maybe this worked on older compilers?) So, is there anyway to emulate this in C++03 (without using a custom cast operator)?
"Imperfect C++" is right, because it uses a custom "keyword" - actually a function name masquerading as a keyword (not unlike eg.: Tribool's indeterminate). If you try to static_cast you crash against the limitation that the language can only accept conversion chains that involve up to one user-defined type, whereas you have two conversions - from "Foo" to "int_cast" and from there to int.
If you want specifically to be able to static_cast then you'll probably have to hack something with macros to supersede normal static_cast... and accept to live in Undefined Behaviour Land. My preferred choice is to actually work in the inverse direction: simply use explicit_cast and use a macro to redefine it as a static_cast invocation when in C++11 mode. I use explicit cast in my C++ backports toolkit and thus in all the C++ code I write, and I have found no important issues so far.

c++ conversion operator overloading, enums, ints and chars

When I try to compile (with gcc 4.3.4) this code snippet:
enum SimpleEnum {
ONEVALUE
};
void myFunc(int a) {
}
void myFunc(char ch) {
}
struct MyClass {
operator int() const { return 0; };
operator SimpleEnum() const { return ONEVALUE; };
};
int main(int argc, char* argv[]) {
myFunc(MyClass());
}
I get this error:
test.cc: In function "int main(int, char**)":
test.cc:17: error: call of overloaded "myFunc(MyClass)" is ambiguous
test.cc:5: note: candidates are: void myFunc(int)
test.cc:8: note: void myFunc(char)
I think I (almost) understand what the problem is, i.e. (simplifying it a lot) even if I speak about "char" and "enum", they all are integers and then the overloading is ambiguous.
Anyway, the thing I don't really understand is that if I remove the second overloading of myFunc OR one of the conversion operators of MyClass, I have no compilation errors.
Since I'm going to change A LOT of old code because of this problem (I'm porting code from an old version of HP-UX aCC to g++ 4.3.4 under Linux), I would like to understand better the whole thing in order to choose the best way to modify the code.
Thank you in advance for any help.
The conversion from MyClass is ambiguous, as there is one conversion to int and one to the enum, which is itself implicitly convertible to int, and both are equally good conversions. You can just make the call explicit, though, by specifying which conversion you want:
myfunc(int(MyClass()));
Alternatively, you might like to rethink why you have a function that has separate overloads for int and char, perhaps that could be redesigned as well.
enums are types in C++, unlike C.
There are implicit conversions for both enum -> char and enum -> int. The compiler just doesn't know which one to choose.
EDIT: After trying with different tests:
When the definition for custom conversion MyClass -> int is removed, code compiles.
Here there is implicit conversion for enum to int and so it is the one favored by the compiler over the one to char. Test here.
When the definition for void myFunc(int) is removed compilation fails.
Compiler tries to convert from MyClass to char and finds that, not having a user defined conversion operator char(), both user defined int() and SimpleEnum() may be used. Test here.
When you add a char() conversion operator for MyClass compilation fails with the same error as if not.
Test here.
So the conclusion I come up with here is that in your originally posted code compiler has to decide which of the two overloaded versions of myFunc should be called.
Since both conversions are possible:
MyClass to int via user defined conversion operator.
MyClass to int via user defined conversion (MyClass to SimpleEnum) + implicit conversion (SimpleEnum to char)
compiler knows not which one to use.
I would have expected that the int overload is called. Tried a few compilers and got different results. If you are going to remove anything, remove the user conversion operator to int, since enums have a standard conversion to ints.