Name lookup, point of instantiation (POI) and fundamental types

Viewed 58

The following code compiles for X, but not for double:

struct X{};

void foo(double);
void foo(X);

namespace NN { 
struct A{};
void foo(A)
{
  foo(double{});  // error: foo not found
  foo(X{});
}

}

The problem here seems to be, that ADL kicks in for X, but not for double. One could solve this by moving the foo(A) out of namespace NN. But this makes trouble, if you need to delay the name lokup to the POI as in the following snippet:

void foo(double);

template<class T>
void bar(T x) { foo(x); }

namespace NN {
template<class T> struct A {};

template<class T>
void foo(const A<T>& x)
{
  using ::foo;  // this is required
  foo(T{});
}

}

void baz() { bar(NN::A<double>{}); }

Here you cannot move void foo(const A<T>& x) out of namespace NN, since then bar couldn't find the right foo (and it fails to compile). The only solution I came up to break this cycle was the explicit addition of the using ::foo in the foo overload.

Question: is this the canonical solution for this problem or is there a better solution?

One could argue, that there could be a list of namespaces necessary in the foo implementation. OTOH, maybe it is only necessary for fundamental types, since for other types (even in the global scope) the proper function is in the overload set.

0 Answers
Related