Overloading == and != - c++

I was on here earlier to get some information on overloading *= and found it very helpful.
I am now trying to overload == and !=. But I want to make the operator functions non-member functions.
Try not to hate all my code blocks - I have included what I believe to be relevant to the issues.
In my source code, I declare the functions:
bool operator==(const Statistician&, const Statistician&);
// checks whether Stat1 == Stat2
bool operator!=(const Statistician&, const Statistician&);
// checks whether Stat1 != Stat2
Later on I define the functions:
// Check if equal
bool operator==(const Statistician& Stat1, const Statistician& Stat2)
{
if ((Stat1.get_length() == Stat2.get_length()) &&
(Stat1.get_sum() == Stat2.get_sum()) &&
(Stat1.get_mean() == Stat2.get_mean()) &&
(Stat1.get_minimum() == Stat2.get_minimum()) &&
(Stat1.get_maximum() == Stat2.get_maximum()))
return true;
else
return false;
}
// Check if not equal
bool operator!=(const Statistician& Stat1, const Statistician& Stat2)
{
if ((Stat1.get_length() != Stat2.get_length()) &&
(Stat1.get_sum() != Stat2.get_sum()) &&
(Stat1.get_mean() != Stat2.get_mean()) &&
(Stat1.get_minimum() != Stat2.get_minimum()) &&
(Stat1.get_maximum() != Stat2.get_maximum()))
return true;
else
return false;
}
In my test driver, I do the actual testing:
if (Stat1 == Stat2) { cout << "Equal"; }
if (Stat1 != Stat2) { cout << "Not Equal"; }
The rest of my code works fine, and these are again not class member functions.
But when I compile I get these errors:
error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Statistician' (or there is no acceptable conversion)
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(507): could be 'bool std::operator ==(const std::exception_ptr &,const std::exception_ptr &)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(512): or 'bool std::operator ==(std::nullptr_t,const std::exception_ptr &)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(517): or 'bool std::operator ==(const std::exception_ptr &,std::nullptr_t)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\system_error(426): or 'bool std::operator ==(const std::error_code &,const std::error_condition &) throw()'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\system_error(434): or 'bool std::operator ==(const std::error_condition &,const std::error_code &) throw()'
while trying to match the argument list '(Statistician, Statistician)'
error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'Statistician' (or there is no acceptable conversion)
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(522): could be 'bool std::operator !=(const std::exception_ptr &,const std::exception_ptr &)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(527): or 'bool std::operator !=(std::nullptr_t,const std::exception_ptr &)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(532): or 'bool std::operator !=(const std::exception_ptr &,std::nullptr_t)'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\system_error(443): or 'bool std::operator !=(const std::error_code &,const std::error_condition &) throw()'
c:\program files (x86)\microsoft visual studio 11.0\vc\include\system_error(450): or 'bool std::operator !=(const std::error_condition &,const std::error_code &) throw()'
while trying to match the argument list '(Statistician, Statistician)'
After much internet research I still don't know what those errors mean.

First of all, your operator!= is wrong, it should be
if ((Stat1.get_length() != Stat2.get_length()) ||
(Stat1.get_sum() != Stat2.get_sum()) ||
(Stat1.get_mean() != Stat2.get_mean()) ||
(Stat1.get_minimum() != Stat2.get_minimum()) ||
(Stat1.get_maximum() != Stat2.get_maximum()))
return true;
else
return false;
(note || instead of &&). Better yet, make that
return !(Stat1==Stat2);
Now for the error you see: It looks like you forgot to include the header which declares these operators in the translation unit where you are using them. Or, if that is not the case, you need to check which namespaces they are in and if they can be found there from where they are called.
Just to check: If you say "In my source code, I declare the functions:" you mean the header-file (*.h) and with "later on" you mean the implementation file (*.cc), right?

Related

Different iterator behavior of raw array and std::array on clang++ and VC++

Consider following program:
#include <iostream>
#include <algorithm>
#include <array>
bool greater_than_seven(int i) {
return i > 5;
}
bool divisible_by_five(int x) {
return ((x%5)==0);
}
int main() {
int arr[]{3,6,9,12,15};
std::cout<<"Enter a number you want to search: ";
int num;
std::cin>>num;
auto result(std::find(std::begin(arr),std::end(arr),num));
if(result != std::end(arr))
std::cout<<"arr contains: "<<num<<'\n';
else
std::cout<<"arr doesn't contain: "<<num<<'\n';
for(result=std::find_if(std::begin(arr),std::end(arr),greater_than_seven);result!=std::end(arr);++result)
std::cout<<*result<<' ';
std::cout<<'\n';
std::array<int,4> x{33,66,99,55};
for(result=std::find_if_not(std::begin(x),std::end(x),divisible_by_five);result!=std::end(x);++result)
std::cout<<*result<<'\n';
}
This program compiles fine on g++ & clang++.
See live demo here ( g++ 5.4.0 )
See live demo here ( clang++ 3.8.0 )
But it gives horrible compiler error on Microsoft Visual C++ compiler.
See live demo here ( Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64 )
Error(s):
source_file.cpp(27): error C2440: '=': cannot convert from 'std::_Array_iterator<_Ty,4>' to 'int *'
with
[
_Ty=int
]
source_file.cpp(27): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
source_file.cpp(27): error C2679: binary '!=': no operator found which takes a right-hand operand of type 'std::_Array_iterator<_Ty,4>' (or there is no acceptable conversion)
with
[
_Ty=int
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\exception(343): note: could be 'bool std::operator !=(const std::exception_ptr &,const std::exception_ptr &) throw()' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\exception(348): note: or 'bool std::operator !=(std::nullptr_t,const std::exception_ptr &) throw()' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\exception(353): note: or 'bool std::operator !=(const std::exception_ptr &,std::nullptr_t) throw()' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(388): note: or 'bool std::operator !=(const std::error_code &,const std::error_code &) noexcept' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(395): note: or 'bool std::operator !=(const std::error_code &,const std::error_condition &) noexcept' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(402): note: or 'bool std::operator !=(const std::error_condition &,const std::error_code &) noexcept' [found using argument-dependent lookup]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\system_error(409): note: or 'bool std::operator !=(const std::error_condition &,const std::error_condition &) noexcept' [found using argument-dependent lookup]
source_file.cpp(27): note: while trying to match the argument list '(int *, std::_Array_iterator<_Ty,4>)'
with
[
_Ty=int
]
So the question is which compiler is right here according to C++ standard ? Is this bug in VC++ compiler ?
Is this bug in VC++ compiler ?
No.
You're assigning and comparing the iterators got from std::begin and std::end on raw array (i.e. result, std::find(std::begin(arr),std::end(arr),num)) and std::array (i.e. std::find_if_not(std::begin(x),std::end(x),divisible_by_five) and std::end(x)), you might be supposing that the types of them are the same.
For raw arrays it'll be T*, i.e. int* for this case, this is guaranteed. The problem is that the standard doesn't specify the exact type of std::array::iterator, it just says it must satisfy the requirements of RandomAccessIterator. Gcc and Clang choose the int* as its type, this is fine because the raw pointer satisfy the requirements. VC implements it as a customized class, this is fine too so long as the type satisfies the requirements. And note that that type doesn't have to be able to convert to int*; the standard doesn't require that at all.
So even your code works with Gcc and Clang, it's not guaranteed.

What does the istream extraction operator >> return?

I'm trying to get Solipsis to compile in Visual Studio 2017(it was written for VS 2005)
I can't figure out what this code is trying to do:
template<typename T>
bool from_string( const char* Str, T & Dest )
{
// créer un flux à partir de la chaîne donnée
std::istringstream iss( Str );
// tenter la conversion vers Dest
return iss >> Dest != 0;
}
It gets the following error
1>c:\users\root\source\repos\solipsis3d\sources\modelers\mdlrtools\include\SolipsisErrorHandler.h(91): error C2678: binary '!=': no operator found which takes a left-hand operand of type 'std::basic_istream<char,std::char_traits<char>>' (or there is no acceptable conversion)
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\exception(347): note: could be 'bool std::operator !=(const std::exception_ptr &,const std::exception_ptr &) throw()' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\exception(352): note: or 'bool std::operator !=(std::nullptr_t,const std::exception_ptr &) throw()' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\exception(357): note: or 'bool std::operator !=(const std::exception_ptr &,std::nullptr_t) throw()' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\system_error(379): note: or 'bool std::operator !=(const std::error_code &,const std::error_code &) noexcept' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\system_error(384): note: or 'bool std::operator !=(const std::error_code &,const std::error_condition &) noexcept' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\system_error(389): note: or 'bool std::operator !=(const std::error_condition &,const std::error_code &) noexcept' [found using argument-dependent lookup]
1>C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\system_error(394): note: or 'bool std::operator !=(const std::error_condition &,const std::error_condition &) noexcept' [found using argument-dependent lookup]
1>c:\users\root\source\repos\solipsis3d\sources\modelers\mdlrtools\include\SolipsisErrorHandler.h(91): note: or 'built-in C++ operator!=(bool, int)'
1>c:\users\root\source\repos\solipsis3d\sources\modelers\mdlrtools\include\SolipsisErrorHandler.h(91): note: while trying to match the argument list '(std::basic_istream<char,std::char_traits<char>>, int)'
1>src\Object3D.cpp(220): note: see reference to function template instantiation 'bool Solipsis::from_string<bool>(const char *,T &)' being compiled
1> with
1> [
1> T=bool
1> ]
1>c:\users\root\source\repos\solipsis3d\sources\modelers\mdlrtools\include\SolipsisErrorHandler.h(91): error C2446: '!=': no conversion from 'int' to 'std::basic_istream<char,std::char_traits<char>>'
1>c:\users\root\source\repos\solipsis3d\sources\modelers\mdlrtools\include\SolipsisErrorHandler.h(91): note: Constructor for class 'std::basic_istream<char,std::char_traits<char>>' is declared 'explicit'
1>SolipsisErrorHandler.cpp
In human language what is the return value of the '>>' operator(when used as for extraction not bit shift)? What has changed about it since VS 2005 that makes the code snippet not work?
I can't figure out what this code is trying to do:
The code is trying to return whether the stream extraction was successful or not.
What does the istream extraction operator >> return?
It is not the case that the return type of the operator is breaking your compilation, but rather because of a change in behaviour since C++11.
Prior to C++11 (say with VS2005) you could check for success/failure by comparing the istream object with true/false.
return iss >> Dest != 0;
You can't do that with a C++11 compilation (say with VS2017), and the reasons are given in the excellent answer to the suggested duplicate question:
Evaluating stream operator >> as boolean
Rather modernise your function by casting to a boolean.
return bool(iss >> Dest);

SFML and STL: What's wrong with my code?

I have the following code snippets:
void RemoveButton::triggerAction(team &team, unsigned int index)
{
switch (mAction)
{
case Action::remove:
{
//team.mTeamMembers.erase(std::remove(team.mTeamMembers.begin(), team.mTeamMembers.end(), team.mTeamMembers.at(index)), team.mTeamMembers.end());
team.mTeamMembers.erase(team.mTeamMembers.begin() + index);
for (unsigned int i = index; i < team.mTeamMembers.size(); i++)
{
team.mTeamMembers[i].mRemoveButton->getText().move(0.0f, -30.0f);
team.mTeamMembers[i].mText.move(0.0f, -30.0f);
}
team.mAddPosition.y -= 30.0f;
break;
}
default:break;
}
}
class team
{
public:
size_t teamNumber;
std::vector<AddButton> mAddButtons;
std::vector<teamRecord> mTeamMembers;
sf::Sprite mBorder;
sf::Text mText;
Selector<AddButton> mAddButtons_Selector;
sf::Vector2f mAddPosition;
Selector<teamRecord> mTeamMembers_Selector;
team(sf::Vector2f borderPosition, sf::Vector2f removeButtonsPosition, sf::Vector2f textPosition, size_t teamNumb, std::string text);
};
How should I erase an element from the team.mTeamMembers STL vector? The way I do it currently results in seemingly random execution errors, specifically when clicking the non-existent sprite of a deleted button. The commented line that uses std::remove is not compiled, and I do not understand why. As I'm feeling confused a.f. , can someone please shine some light here? Here's the build log while using std::remove, as recommended by some users on this forum:
1>------ Build started: Project: Complex OOP Menus, Configuration: Release Win32 ------
1> RemoveButton.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\algorithm(1454): error C2678: binary '==': no operator found which takes a left-hand operand of type 'teamRecord' (or there is no acceptable conversion)
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\system_error(389): note: could be 'bool std::operator ==(const std::error_condition &,const std::error_condition &) noexcept'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\system_error(381): note: or 'bool std::operator ==(const std::error_condition &,const std::error_code &) noexcept'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\system_error(373): note: or 'bool std::operator ==(const std::error_code &,const std::error_condition &) noexcept'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\system_error(365): note: or 'bool std::operator ==(const std::error_code &,const std::error_code &) noexcept'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\exception(339): note: or 'bool std::operator ==(const std::exception_ptr &,std::nullptr_t) throw()'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\exception(334): note: or 'bool std::operator ==(std::nullptr_t,const std::exception_ptr &) throw()'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\exception(329): note: or 'bool std::operator ==(const std::exception_ptr &,const std::exception_ptr &) throw()'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\algorithm(1454): note: while trying to match the argument list '(teamRecord, const teamRecord)'
1> C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\algorithm(1467): note: see reference to function template instantiation '_FwdIt std::_Remove_unchecked<teamRecord*,_Ty>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1> with
1> [
1> _FwdIt=teamRecord *,
1> _Ty=teamRecord
1> ]
1> ..\Data\Source\RemoveButton.cpp(24): note: see reference to function template instantiation '_FwdIt std::remove<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<teamRecord>>>,teamRecord>(_FwdIt,_FwdIt,const _Ty &)' being compiled
1> with
1> [
1> _FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<teamRecord>>>,
1> _Ty=teamRecord
1> ]
If there is not enough information here, I could post the github link to my project, but it's pretty big and it would take time to sift through the code.
Using std::remove() doesn't make any sense to me if you already know the position/offset and you only want to remove a single entry.
You're receiving your error with std::remove() most likely due to the fact that there's no equality operator (operator ==) defined for your teamRecord class (or it just isn't found).
The way I do it currently results in seemingly random execution errors, specifically when clicking the non-existent sprite of a deleted button.
That's something we can't look at unless we see the code regarding that. How can you click something not existing? Any chance you're just missing a check or not cleaning up things properly?
I solved this by double checking the index I was giving to the elements on insertion. Thanks and sorry for such a stupid mistake!

Error with xstdde "could not deduce template argument..."

I'm working on a asteroids game replica. This error I'm getting is beyond my understanding so I hope you can help.
In my code I have a class name asteroid that stores every asteroid object. Within this class I have a public function that's called create() which has the parameter sf::ConvexShape (if you don't know what sf::ConvexShape is, it is a function in the SFML library). I also have a std::map<asteroid, sf::ConvexShape> to store asteroid objects as the key and their shapes as the .second
The error is a runtime error, everything is fine in the compiler. The error reports are gibberish to me, but there was a part that mentioned "iterator" and "std::vector" which makes me think I'm doing something wrong passing iterators to the create() function?
Here is the error log:
Error 5 error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 10 error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 12 error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 9 error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 8 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 6 error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 4 error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 11 error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 7 error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const asteroid' C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Error 13 error C2676: binary '<' : 'const asteroid' does not define this operator or a conversion to a type acceptable to the predefined operator C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\xstddef 180 1 SFML testing
Also full sauce here.
Why am I getting these errors? How can I fix it?
Let me know if there is something I forgot to mention, its hard to know what to ask when I don't understand the problem.
std::map stores things in a sorted order. If you don't tell it how to sort, it will use operator <. Your problem is that given:
asteroid a, b;
a < b; // Not defined.
You need something like:
bool operator <( const asteroid& lhs, const asteroid& rhs)
{
????
}
Except that you can't use the position (because that keeps changing). Perhaps you should do:
class asteroid
{
static unsigned global_id;
unsigned id;
.... // Previous contents as before.
}
asteroid::asteroid() : id (global_id++) { ... }
and then
bool operator <( const asteroid& lhs, const asteroid& rhs)
{
lhs.id < rhs.id;
}

Operator precedence change

The following used to build OK on VS2008 but on VS2013, it moans. OK in g++.
#include <sstream>
int main()
{
int a = 2, b = 5;
std::ostringstream oss;
oss << a == 0 ? a : b;
}
The error message is
1>u:\precedence\precedence.cpp(7): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::basic_ostream<char,std::char_traits<char>>' (or there is no acceptable conversion)
1> c:\program files\microsoft visual studio 12.0\vc\include\exception(497): could be 'bool std::operator ==(const std::exception_ptr &,const std::exception_ptr &)' [found using argument-dependent lookup]
1> c:\program files\microsoft visual studio 12.0\vc\include\exception(502): or 'bool std::operator ==(std::nullptr_t,const std::exception_ptr &)' [found using argument-dependent lookup]
1> c:\program files\microsoft visual studio 12.0\vc\include\exception(507): or 'bool std::operator ==(const std::exception_ptr &,std::nullptr_t)' [found using argument-dependent lookup]
1> c:\program files\microsoft visual studio 12.0\vc\include\system_error(402): or 'bool std::operator ==(const std::error_code &,const std::error_condition &) throw()' [found using argument-dependent lookup]
1> c:\program files\microsoft visual studio 12.0\vc\include\system_error(410): or 'bool std::operator ==(const std::error_condition &,const std::error_code &) throw()' [found using argument-dependent lookup]
1> while trying to match the argument list '(std::basic_ostream<char,std::char_traits<char>>, int)'
It works on both versions if the output statement is changed to
oss << (a == 0? a: b);
I can force a different error in VS2008 if a constant is not used: something like
int zero = 0;
oss << a == zero? a: b;
Just wondering why there is an error when a constant is not used.
Edit Managed to get an warning with g++ with -Wall.
The expression the compiler sees due to the precedence is, in all cases:
((oss << a) == 0) ? a : b;
Now oss << a returns oss. How can you compare oss with 0? It has an implicit conversion operator operator void *.
VS2013 presumably replaced that with explicit operator bool for C++11 (the whole point of which was so that these hard-to-find bugs don't occur). libstdc++ has not done this replacement to my knowledge. It must in order to conform with C++11.
Now why doesn't zero compile? zero is not a null pointer constant, but 0 is. Thus, the latter can be compared to the pointer returned by operator void *.
In any case, the simple way to fix this so it should work properly with any conforming implementation is to add parentheses:
oss << (a == 0 ? a : b);
It appears that the compiler is interpreting it different.
Based on the error, I would suspect that the compiler is interpreting the line of code like this
(oss << a) == 0 ? a : b;
So when you put in the parens there was no longer any way it could interpret it that way, and you got the expected results.
I suspect that this would also work.
oss << (a == 0) ? a : b;