Unnamed namespace and iostream result in "!= being illegal operation" - c++

#include <functional>
#include <iostream>
struct A {
friend bool operator==( const A & a, const A & b ){
return true;
}
};
namespace {
bool operator!=( const A &a, const A & b){
return !(a==b);
}
}
int main(int argc, char **argv) {
std::not_equal_to<A> neq;
A a;
bool test = neq(a, a);
return test ? 0 : 1;
}
This fails on CC (SunOs Compiler) with:
Error: The operation "const A != const A" is illegal.
"tempcc.cpp", line 16: Where: While instantiating "std::not_equal_to<A>::operator()(const A&, const A&) const".
"tempcc.cpp", line 16: Where: Instantiated from non-template code.
And on g++ with:
/usr/local/include/c++/3.3.2/bits/stl_function.h: In member function `bool std::not_equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = A]':
tempcc.cpp:16: instantiated from here
/usr/local/include/c++/3.3.2/bits/stl_function.h:183: error: no match for 'operator!=' in '__x != __y'
However if I remove the line #include <iostream> it compiles and runs just fine. Anyone dare to explain this?

According to Comeau, this isn't legal either way - the fact that the compiler builds it when you don't #include <iostream> may be the actual bug, not the other way around (or at least a disagreement in interpretation):
"stl_function.h", line 99: error: no operator "!=" matches these operands
operand types are: const A != const A
bool operator()(const _Tp& __x, const _Tp& __y) const { return __x != __y; }
^
detected during instantiation of "bool
std::not_equal_to<_Tp>::operator()(const _Tp &, const _Tp
&) const [with _Tp=A]" at line 19 of "ComeauTest.c"
"ComeauTest.c", line 10: warning: function "<unnamed>::operator!=" was declared but
never referenced
bool operator!=( const A &a, const A & b){
^
It makes sense that this doesn't build - placing operator!= in an unnamed namespace still puts it in a different namespace than ::, and I'm not entirely sure why g++ builds it without the iostream include - if you look at the preprocessor output from g++ it hasn't done anything hinky to reorder code or any such nonsense, and of course iostream doesn't define operator!= for A.
I do not have my copy of the C++ standard handy, but this link from IBM at least validates the claim that unnamed namespaces don't mix that well with the global one, explaining why you can't find the operator!= you've defined.
You also might find some helpful information in Anonymous Namespace Ambiguity.

The problem is that <functional> also pulls in several templates from from tuple and utility that interfere with the lookup.
If you were to remove this, e.g. by only including <bits/stl_function.h> in GCC, then there is no problem, although is is of course not a real solution. I suppose you cannot get around either implementing your own operator!=() or adding an explicit specialization for std::not_equal_to if you require the predicate.
However, if you don't need to use the not_equal_to predicate, you can circumvent the problem entirely by removing all your custom code and adding the following:
#include <utility>
using namespace std::rel_ops;
bool test = a != a;

Related

"no match" and "cannot bind lvalue" errors while overloading `operator<<` with `std::wostream` and `std::string`

I've got an error while overloading std::wostream::operator<<() for std::string.
Here is the minimal test case illustrating my problem:
#include <string>
#include <sstream>
inline std::wostream &operator<<(std::wostream &os, const std::string &)
{
return os;
}
class FakeOstream{};
namespace mynamespace {
class FakeClasse1 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse1 &) {
return out;
}
};
class FakeClasse2 {
friend inline FakeOstream &operator<<(FakeOstream &out, const FakeClasse2 &) {
return out;
}
};
void test()
{
auto mystring = std::string{u8"mystring"};
std::wostringstream s;
s << mystring; // The errors occur here
}
} // namespace mynamespace
The code can be compiled and executed here: http://cpp.sh/9emtv
As you can see here, there is an overload for operator<< with std::wostream
and std::string. The two fake classes are empty apart from the declaration of
an operator<< with FakeOstream and themselves. The test() function
instantiate an std::wostringstream and feed it a std::string. The fake
fake classes and test function are in a namespace.
This code yields the following error on cpp.sh at the line s << mystring;:
In function 'void mynamespace::test()':
25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
In file included from /usr/include/c++/4.9/istream:39:0,
from /usr/include/c++/4.9/sstream:38,
from 2:
/usr/include/c++/4.9/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::basic_string<char>]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
When using directly g++ (version 5.3.0 from MSYS2), a no match error is also
displayed:
./tmpbug.cpp: In function 'void mynamespace::test()':
./tmpbug.cpp:25:7: error: no match for 'operator<<' (operand types are 'std::wostringstream {aka std::__cxx11::basic_ostringstream<wchar_t>}' and 'std::__cxx11::basic_string<char>')
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: candidate: std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Tp = std::__cxx11::basic_string<char>] <near match>
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
C:/Appli/msys64/mingw64/include/c++/5.3.0/ostream:628:5: note: conversion of argument 1 would be ill-formed:
./tmpbug.cpp:25:10: error: cannot bind 'std::basic_ostream<wchar_t>' lvalue to 'std::basic_ostream<wchar_t>&&'
s << mystring;
^
In file included from C:/Appli/msys64/mingw64/include/c++/5.3.0/istream:39:0,
from C:/Appli/msys64/mingw64/include/c++/5.3.0/sstream:38,
from ./tmpbug.cpp:2:
As far as I know, all the parts of the example are necessary for the errors to
appear. If I comment out the namespace, the fake classes or just one of the
operator<< in the fake classes, the code compile just fine. Moreover, if I
just move one of the fake classes or the test function outside of the namespace,
the code will also compile just fine.
Additionnally, I tried compiling this example on clang 3.7 by using the compiler
from http://cppreference.com, and the code seems to compile without problems.
Is there a problem with my code or is this a GCC bug ? If this is a GCC bug, is
there a workaround ?
This is a bad idea:
inline std::wostream &operator<<(std::wostream &os, const std::string &)
as you should not overload operators on two types in std that do not depend on your own (outside of std or build-in) types. Doing ... doesn't work well. And, in my opinion, shouldn't be allowed.
Regardless, you can generate the same problem with conforming code by simply creating your own namespace notstd and own type notstd::string, then in the global root namespace defining
inline std::wostream &operator<<(std::wostream &os, const notstd::string &)
{
return os;
}
and get the same symptoms. So that doesn't matter much.
Operators are found first via unqualified name lookup, then via argument dependent lookup.
As we have no using statement, unqualified name lookup first looks in the enclosing namespace. If nothing is found, the namespaces containing it (and eventually the file/global namespace) are then searched.
ADL then augments this with operators found via ADL or Koenig lookup -- it looks in the namespaces of the arguments and their template parameters.
Now, the friend operator<< you defined do live in the namespace their class contains, but they are usually difficult to find.
Somehow your double-declaration of friend operator<< is making your code find them, and stop looking into the global namespace for a <<.
To me this looks like a bug. Neither of those "Koenig operators" should be visible to bog-standard unqualified name lookup with types unrelated to the classes they are "contained" in.
MCVE:
#include <iostream>
#include <sstream>
namespace notstd {
struct string {};
}
inline void operator<<(std::wostream &os, const notstd::string &){ return; }
class FakeOstream{};
namespace mynamespace {
class UnusedClass1 {
friend inline void operator<<(FakeOstream &out, const UnusedClass1 &) { return; }
};
class UnusedClass2 {
// comment this line out and the code compiles:
friend inline void operator<<(FakeOstream &out, const UnusedClass2 &) { return; }
};
void test() {
auto mystring = notstd::string{};
std::wostringstream s;
s << mystring; // The errors occur here
}
} // namespace mynamespace
int main(){}
live example.
#T.C. found what appears to be this bug being fixed:
test code
fix in gcc

How to get a custom operator== to work with Google Test?

I'm having trouble using a custom overloaded '==' operator with PCL and Google Test (GTest)
#include <pcl/point_types.h>
namespace pcl { struct PointXYZ; }
bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
#include <gtest/gtest.h>
TEST(Foo, bar) {
pcl::PointXYZ a{2,3,4};
pcl::PointXYZP b{2,3,4};
EXPECT_EQ(a,b); // Compile error no match for operator==
}
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
The error I get is:
|| /usr/include/gtest/gtest.h: In instantiation of 'testing::AssertionResult testing::internal::CmpHelperEQ(const char*, const char*, const T1&, const T2&) [with T1 = pcl::PointXYZ; T2 = pcl::PointXYZ]':
/usr/include/gtest/gtest.h|1361 col 23| required from 'static testing::AssertionResult testing::internal::EqHelper<lhs_is_null_literal>::Compare(const char*, const char*, const T1&, const T2&) [with T1 = pcl::PointXYZ; T2 = pcl::PointXYZ; bool lhs_is_null_literal = false]'
src/foo/src/tests.cpp|20 col 3| required from here
/usr/include/gtest/gtest.h|1325 col 16| error: no match for 'operator==' (operand types are 'const pcl::PointXYZ' and 'const pcl::PointXYZ')
|| if (expected == actual) {
|| ^
/usr/include/gtest/internal/gtest-linked_ptr.h|213 col 6| note: candidate: template<class T> bool testing::internal::operator==(T*, const testing::internal::linked_ptr<T>&)
|| bool operator==(T* ptr, const linked_ptr<T>& x) {
|| ^
/usr/include/gtest/internal/gtest-linked_ptr.h|213 col 6| note: template argument deduction/substitution failed:
/usr/include/gtest/gtest.h|1325 col 16| note: mismatched types 'T*' and 'pcl::PointXYZ'
I tried to adhere to the primer:
https://github.com/google/googletest/blob/master/googletest/docs/primer.md#binary-comparison
In particular, my operator is defined before including gtest, and I'm sure the types match up. I also tried writing the overload to take const references, but that just compared the addresses instead of the values.
Operators on custom types are found through argument dependent lookup.
Argument dependent lookup (in a nutshell) means that functions may be considered if they are defined in the same namespace as one or more of their arguments.
This code:
namespace pcl { struct PointXYZ; }
bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
defines PointXYZ in the pcl:: namespace, but defines the operator== function in the global namespace. Hence, not a candidate for ADL.
doing this:
namespace pcl {
struct PointXYZ;
bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
}
Fixes that because now the operator== has the name pcl::operator== which is in the same namespace as one of its arguments (actually in this case both of them, but you get the idea). This makes it a candidate during ADL and thus it will be selected when gtest invokes the equality test.
Include the operator== definition within the namespace pcl:
#include <pcl/point_types.h>
namespace pcl
{
bool operator==(pcl::PointXYZ p1, pcl::PointXYZ p2) {return p1.x-p2.x<.1;}
}
Besides, you can remove the forward declaration for pcl::PointXYZ since it must be complete in header pcl/point_types.h. Otherwise, compiler would complain when defining variables within TEST.
If not defined, you will also have to define operator<<(std::ostream&, const pcl::PointXYZ&) so that Google Test can print out your values when the equality assertion fails.

Why does this C++ generic function work by reference but doesn't work by value? [duplicate]

#include <iostream>
using namespace std;
template<typename T>
T max(T lhs, T rhs)
{
return lhs < rhs ? rhs : lhs;
}
template<>
int max<int>(int lhs, int rhs)
{
return lhs < rhs ? rhs : lhs;
}
int main()
{
cout << max<int>(4, 5) << endl;
}
~/Documents/C++/boost $ g++ -o testSTL testSTL.cpp -Wall
testSTL.cpp: In function ‘int main()’:
testSTL.cpp:18:24: error: call of overloaded ‘max(int, int)’ is ambiguous
testSTL.cpp:11:5: note: candidates are: T max(T, T) [with T = int]
/usr/include/c++/4.5/bits/stl_algobase.h:209:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
How do I correct this error?
It's all because of your using namespace std;. Remove that line.
By that using-directive, you bring std::max (which must be somehow included via iostream) into the global scope. Therefore the compiler doesn't know which max to call - ::max or std::max.
I hope this example will be a good scarecrow for those who think that using directives come at no cost. Weird errors are one side effect.
I guess the compiler can't work out whether to use std::max or your max, because you've got a using namespace std; and both your max and the std::max fit the bill
You're colliding with std::max(). Rename it to something else like mymax and it will work.
You have both your max and std::max. The compiler doesn't know which one you intended to call.
You can tell it by calling ::max(4,5) or std::max(4,5), or - even better - not have using namespace std in the file.
That's because there's already std::max template function defined.
Remove the 'using namespace std' and add 'std::' where needed., or use '::max'.
The problem is that there is already a function named 'max' defined by std. To fix this, rename your function to something else, like this:
#include <iostream>
using namespace std;
template<typename T>
T mymax(T lhs, T rhs)
{
return lhs < rhs ? rhs : lhs;
}
template<>
int mymax<int>(int lhs, int rhs)
{
return lhs < rhs ? rhs : lhs;
}
int main()
{
cout << mymax<int>(4, 5) << endl;
return 0;
}

when using templates C++ "const" mystery overloaded function call

I have a question with the code below. When I compile it it complains with this error below. Now my question is if I remove the "const" in the declaration and change it to only :
template<class T> T max( T& left, T& right);
it becomes okay and the compiles/executes correctly. How come the compiler thinks that the call is ambiguous? Shouldn't the forward declaration follow the implementation?
==== start of error message====
max.cpp:10:34: error: call of overloaded ‘max(int, int)’ is ambiguous
max.cpp:10:34: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = int]
/usr/include/c++/4.6/bits/stl_algobase.h:210:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
max.cpp:11:44: error: call of overloaded ‘max(double, double)’ is ambiguous
max.cpp:11:44: note: candidates are:
max.cpp:5:21: note: T max(const T&, const T&) [with T = double]
=======end of error message===
=============code starts here======
#include<iostream>
using namespace std;
template<class T> T max(const T& left, const T& right);
int main(void)
{
cout<<"max int:"<< max(1,4)<<endl;
cout<<"max double:"<< max(5.02,1.002)<<endl;
}
template<class T>
T max(const T& left, const T& right)
{
return left > right? left:right;
}
You have to do:
cout<<"max int:"<< ::max(1,4)<<endl;
cout<<"max double:"<< ::max(5.02,1.002)<<endl;
Since there is another max defined in std namespace. You have to inform the compiler to use the max defined in global namespace, which is the one you defined. See a live example here: Function template Demo
If you look at the std::max defined in std namespace:
template <class T> const T& max (const T& a, const T& b);
which returns const reference and takes const reference to parameters, that's why when you remove const, it will compile. Hope that this helps.
The std namespace has a max already built in, so you can either not have the line using namespace std; or put the max function in your own namespace.
namespace myNamespace {
//your max function
}
We have few functions already defined in std namespace like max(), swap() qsort(). So when you define your own function
max(const T& left,const T& right)
it is same as one in std namespace hence the error. So you can do following to make it work
call your function using scope resolution operator ::max(x,y)
remove const qualifier from your function
As others have written the compiler has found a max function additionally in namespace std. Now it tries to get the best version for you via function overloading. As both signatures are eaqual it can not choose a best version and complains. Now if you remove const the compiler can not bind a integer (or double) literal to a non const refference. Now it has only one choice and takes std::max functionality. You can see it with the following example:
#include <iostream>
namespace ns1 {
template<class T>
void doit(T const&) {
std::cout << "ns1::doit" << std::endl;
}
}
template<class T>
void doit(T&) {
std::cout << "::doit" << std::endl;
}
int main() {
using namespace ns1;
int i=1;
int const j=1;
doit(1);
doit(i);
doit(i+1-1);
doit(j);
return 0;
}
As everithing is an int the compiler has to choose a non const reference only if it has a non const variable (i). In other cases it choose the cont reference version from namespace ns1. It could even bind temporaries to const references (i+1-1).The same happens with your max and std::max.
Edit:
I forgott to say if you remove the const in your declaration the compiler choose std::max which is of course correct but not yours.

error: call of overloaded ‘max(int, int)’ is ambiguous

#include <iostream>
using namespace std;
template<typename T>
T max(T lhs, T rhs)
{
return lhs < rhs ? rhs : lhs;
}
template<>
int max<int>(int lhs, int rhs)
{
return lhs < rhs ? rhs : lhs;
}
int main()
{
cout << max<int>(4, 5) << endl;
}
~/Documents/C++/boost $ g++ -o testSTL testSTL.cpp -Wall
testSTL.cpp: In function ‘int main()’:
testSTL.cpp:18:24: error: call of overloaded ‘max(int, int)’ is ambiguous
testSTL.cpp:11:5: note: candidates are: T max(T, T) [with T = int]
/usr/include/c++/4.5/bits/stl_algobase.h:209:5: note: const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = int]
How do I correct this error?
It's all because of your using namespace std;. Remove that line.
By that using-directive, you bring std::max (which must be somehow included via iostream) into the global scope. Therefore the compiler doesn't know which max to call - ::max or std::max.
I hope this example will be a good scarecrow for those who think that using directives come at no cost. Weird errors are one side effect.
I guess the compiler can't work out whether to use std::max or your max, because you've got a using namespace std; and both your max and the std::max fit the bill
You're colliding with std::max(). Rename it to something else like mymax and it will work.
You have both your max and std::max. The compiler doesn't know which one you intended to call.
You can tell it by calling ::max(4,5) or std::max(4,5), or - even better - not have using namespace std in the file.
That's because there's already std::max template function defined.
Remove the 'using namespace std' and add 'std::' where needed., or use '::max'.
The problem is that there is already a function named 'max' defined by std. To fix this, rename your function to something else, like this:
#include <iostream>
using namespace std;
template<typename T>
T mymax(T lhs, T rhs)
{
return lhs < rhs ? rhs : lhs;
}
template<>
int mymax<int>(int lhs, int rhs)
{
return lhs < rhs ? rhs : lhs;
}
int main()
{
cout << mymax<int>(4, 5) << endl;
return 0;
}