C++ constant reference in compare method on different platforms - c++

I have this piece of c++ code for sorting a struct,
const bool operator<(P& p) const {
//...
}
It compiles without any problem on a linux device with "gcc 4.9.2".
But if try it on a windows machine with "gcc 4.7.1" (the one that comes with Code::Blocks 13.12), it gives nasty errors that you can see here http://pastebin.com/S28tD9kc
For compiling in both cases I've used: "g++ -std=c++11"
If I change "operator<(P& p)" to "operator<(const P& p)" it magically works. OK no problem I've made some mistake, but why does the first one not work on a windows machine if it works on a linux machine without any sign of problem?
An example.

This is probably because in those gcc versions sort is implemented differently. I have checked under VS2005 and it also produces such errors, but from looking into my stl implementation - I see lots of const T& parameters used when sorting. This will cause the same error you see if operator< is used with no const& parameter. I was able to compile such code using custom comparator and const_cast:
struct my_comp {
bool operator() (const P& a, const P& b) const {
return const_cast<P&>(a).operator<(const_cast<P&>(b));
}
};
std::vector<P> pp(10);
std::sort(pp.begin(), pp.end(), my_comp());
I am not sure if this is correct code,just wrote it for compile experiment.
On the other hand, under Visual Studio 2015 it all compiles fine with non const parameter in operator<. In VS2015 sort uses move semantics, and this is what I suppose makes it compile.

Related

What is the difference between object.operator bool() and (bool) object?

I have a class for which I have overloaded the operator bool explicitly like this :-
class Foo {
explicit operator bool() {
// return_something_here
}
};
However, when I run the following two in gdb I get :-
gdb) p fooobj.operator bool()
$7 = true
gdb) p (bool)(fooobj)
$8 = false
What's the difference between the two invocations and why do they return different things?
Edit :- I'm using the clang compiler.
Note :- The second value (false) is the correct value that I want to be returned using the first syntax. I'm using a codegen so I don't have complete control over what c++ gets generated in case anyone is curious why I don't just use the second syntax.
Even in that case, the difference between the two would still be an unanswered question.
I just ran a few quick tests, and it appears to be that gdb doesn't handle code compiled with clang well. Here is a test program:
#include <iostream>
using namespace std;
class Foo {
public:
Foo() : m_Int(0) {}
operator bool() {
return true; // also tried false here
}
private:
int m_Int;
};
int main()
{
Foo f;
if (f.operator bool()) cout << "operator bool is true.\n";
if ((bool)f) cout << "(bool)f is true.\n";
return 0;
}
When the binary is run, the output is as expected, i.e. (bool)f is the same as f.operator bool(), regardless of the compiler. However, if gdb is used with code build using g++, then the p command behaves correctly. Yet when gdb is run on code built using clang++, I get:
(gdb) print f.operator bool()
Couldn't find method Foo::operatorbool
(gdb)
I'm running clang v. 3.4, gcc v. 4.8.4 on Ubuntu 14.04.
In fact, a quick search revealed this: Is it possible to debug a gcc-compiled program using lldb, or debug a clang-compiled program using gdb?. So, I tried lldb, and it worked as expected. This is consistent with the comment that was added as I was investigating.

Can't get warnings to work for header-only library

I'm creating an header-only library, and I would like to get warnings for it displayed during compilation. However, it seems that only warnings for the "main" project including the library get displayed, but not for the library itself.
Is there a way I can force the compiler to check for warnings in the included library?
// main.cpp
#include "MyHeaderOnlyLib.hpp"
int main() { ... }
// Compile
g++ ./main.cpp -Wall -Wextra -pedantic ...
// Warnings get displayed for main.cpp, but not for MyHeaderOnlyLib.hpp
I'm finding MyHeaderOnlyLib.hpp via a CMake script, using find_package. I've checked the command executed by CMake, and it's using -I, not -isystem.
I've tried both including the library with <...> (when it's in the /usr/include/ directory), or locally with "...".
I suppose that you have a template library and you are complaining about the lack of warnings from its compilation. Don't look for bad #include path, that would end up as an error. Unfortunately, without specialization (unless the templates are used by the .cpp), the compiler has no way to interpret the templates reliably, let alone produce sensible warnings. Consider this:
#include <vector>
template <class C>
struct T {
bool pub_x(const std::vector<int> &v, int i)
{
return v.size() < i;
}
bool pub_y(const std::vector<int> &v, int i)
{
return v.size() < i;
}
};
typedef T<int> Tint; // will not help
bool pub_z(const std::vector<int> &v, unsigned int i) // if signed, produces warning
{
return v.size() < i;
}
class WarningMachine {
WarningMachine() // note that this is private
{
//T<int>().pub_y(std::vector<int>(), 10); // to produce warning for the template
}
};
int main()
{
//Tint().pub_y(std::vector<int>(), 10); // to produce warning for the template
return 0;
}
You can try it out in codepad. Note that the pub_z will immediately produce signed / unsigned comparison warning when compiled, despite never being called. It is a whole different story for the templates, though. Even if T::pub_y is called, T::pub_x still passes unnoticed without a warning. This depends on a compiler implementation, some compilers perform more aggressive checking once all the information is available, other tend to be lazy. Note that neither T::pub_x or T::pub_y depend on the template argument.
The only way to do it reliably is to specialize the templates and call the functions. Note that the code which does that does not need to be accessible for that (such as in WarningMachine), making it a candidate to be optimized away (but that depends), and also meaning that the values passed to the functions may not need to be valid values as the code will never run (that will save you allocating arrays or preparing whatever data the functions may need).
On the other hand, since you will have to write a lot of code to really check all the functions, you may as well pass valid data and check for result correctness and make it useful, instead of likely confusing the hell of anyone who reads the code after you (as is likely in the above case).

Compiler Robustness ... Naivete

I use Visual Studio Professional 2012. I pre-compiled a class (header and source) successfully. Days later, when compiling another class (for the moment header only) that is utilizing the previous one, the compiler caught a missing reference if(this != &rhs) and semicolon rhs.root = nullptr;.
Perhaps it is my naivete and lack of knowledge about how compilers work but I thought a compiler was robust to catch errors such as these. It appeared to me that only when a specific block of code was required did the compiler feel the need to check it.
I have read about just-in-time compilation and learned how assembly compilers perform a two-pass compilation with symbols first and then syntax. I have not taken a course in compiler construction at my university and I know such courses give great insight into parsers, etc.
The code section where it failed to catch the error is this move assignment operator:
Tree &operator=(Tree &&rhs)
{
if(this != rhs) <--------- no reference to the rhs
{
root = std::move(rhs.root);
rhs.root = nullptr <----------- no semicoln
}
return *this;
}
The errors were generated while compiling boost variant, as well as my visitor class member:
bool operator() (Tree<std::string>& tree) const {
return tree.load(tree);
}
as well as a host of other errors related to boost serialization. The fix was to, of course, correct the missing reference and semicolon but I want to understand why this was caught apparently only when the compiler needed to touch this code?
Is it a template class?
Because semantic analysis of templates makes only sense when they are instantiated. That is, if it is a template, the compiler should generate an error at the missing semicolon (syntactic error), but not at the == operator.
The following code compiles with g++:
template<typename T>
struct A {
void q(A &a) {
if (this == a) {}
}
};
int main(int argc, char **argv) {
A<int> x;
//x.q(x);
}
But doesn't compile when
x.q(x);
is uncommented.

Why does scope of using directive make a difference?

Below are two simplified code examples: the first one compiles just fine, the second one emits a compile error (no operator << found which takes a left hand operator ByteVector...).
The only difference in between the two examples is the placement of the using directive.
I don't want to know why it fails (you got not enough information to answer this), I am only interested in why it does make any difference where I place the using.
I would have expected the exact same behaviour in both examples.
Compiles without error
ByteVector Test()
{
using Base::operator <<;
ByteVector foo;
int bar = 1;
foo << bar;
return foo;
}
Compiles with error
using Base::operator <<;
ByteVector Test()
{
...same as above, without using
}
Extra information:
The operator<< used is defined as follows
template<typename T>
ByteVector& operator<<(ByteVector &, const T&){...};
The only thing that comes to my mind is Visual Studio. If that was the case, you may want to put the using directive right after the corresponding #include. As the remark on the page says:
Putt your using directive at the beginning of the source code file to
reduce the potential for unexpected behavior with IntelliSense.
Otherwise, it shouldn't make any difference.

_Dist_type not declared in this scope

I've been tasked with getting some old code working. It's dated from 2006 and I believe it was written in visual studio. I get this error when compiling with g++ 4.5.2 using ming32 on a windows machine and I get the same error compiling with g++ 4.1.2 on a unix machine(not sure what flavor)
"_Dist_type was not declared in this scope"
#include <algorithm>
#include <vector>
template<class ReturnType, class RandomIterator, class _Ty> inline
ReturnType interpolate(RandomIterator _F, RandomIterator _L, const _Ty& _V, RandomIterator _F2)
{
return _Dist_type(_F);
}
class Interpolator
{
public:
double interp(const std::vector<double>& xValues, const std::vector<double>& yValues,
const double x0) const
{
//1-D interpolation
return interpolate<double>(xValues.begin(), xValues.end(), x0, yValues.begin());
}
};
I've tried googling for _dist_Type, but there doesn't seem to be a lot of information out there. I did find one source, but I'm not sure how much it can help. http://en.allexperts.com/q/C-1040/STL-Iterator.htm
It's my understanding that _Dist_type is part of a very old version of the STL library which neither build machine has. How could I solve this? I'm not even sure what the function does.
Any help is greatly appreciated.
_Dist_type is an internal implementation detail used by Visual Studio's standard library. Names starting with an underscore followed by an uppercase letter are reserved by the implementation and must never be called directly from user code.
You'll have to figure out what that function does and duplicate the functionality in a portable manner. If you're lucky you might find that there is a function in the standard library that already implements this functionality and you can just replace the call.
EDIT:
Both Visual Studio 2005 & 2010 have _Dist_type defined as
template<class _Iter> inline
typename iterator_traits<_Iter>::difference_type
*_Dist_type(_Iter)
{ // return distance type from arbitrary argument
return (0);
}
So it is just returning a value of 0 of type std::iterator_traits<RandomIterator>::difference_type