Re: Different results from different gcc versions
Alf P. Steinbach wrote:
* ks:
Hi,
I have a problem with a piece of code. I'm in a situation where I have
to compile code using 2 different g++ compilers (2.95 and 4.12). I've
reduced the issue to a small, self contained program (given below)
//-------------------------------------
START----------------------------
#include <stdio.h>
struct A {
int a;
int b;
} ;
namespace NS {
void func(struct A *, int);
}
void NS::func(struct A * a_ptr, int i)
{
printf("%ld %d\n", a_ptr, i);
This should probably be a p-format.
return;
}
namespace NS {
struct A : public ::A {} ;
}
struct NS::A* get_A(void)
{
return (struct NS::A *) 0;
}
int main()
{
func(get_A(), 1);
}
//--------------------------------
END----------------------------------
This program compiles on g++ 4.12 but fails on g++ 2.95 with the
following error:
test.cpp: In function `int main()':
test.cpp:30: implicit declaration of function `int func(...)'
If I change the call from func(...) to NS::func(...), both the
compilers are happy. I can understand the reason for that. However,
how does the g++ 4.12 compiler build without explicitly specifying the
namespace?
Argument dependent lookup, a.k.a. ADL a.k.a Koenig lookup (after Andrew
Koenig).
Since the type of the argument is "pointer to T" where T is defined in
NS, the overload set for the function includes matching declarations
from NS.
Which is the correct behavior?
ADL.
It's great but it can get pretty tricky and yield unexpected results.
I would have liked for ADL to only apply to operators (where it's
necessary), but it applies to ordinarily named functions, sneaking in
subtleties.
That has some advantages though for generic programming, allowing things
like sqrt, abs which live in the std namespace to work as expected for
user defined types without resorting to UB e.g.:
#include <cmath>
#include <iostream>
namespace thirdpartylib {
class MyBigInt { /* assume implict constructor for int and some
sensible int like operators */ };
MyBigInt sqrt(const MyBigInt&);
}
using std::sqrt;
template <typename T>
T doStuff(const T& a, const T& b) {
return sqrt((a - b) * (a - b));
}
int main() {
int a=1, b=2;
double c=1,d=2;
thirdpartlib::MyBigInt e=1,f=2;
std::cout << doStuff(a,b) << doStuff(c,d) << doStuff(e,f) << std::endl;
return 0;
}