Is it possible to take the address of an ADL function?

argument-dependent-lookup, c++, function-pointers

Solution

Honestly, I don't know but I tend towards saying that this is not possible.

Depending on what you want to achieve I can suggest a workaround. More precisely, if you just need the address of a function that has the same semantics as `swap` called through ADL then you can use this:

template <typename T>
void (*get_swap())(T&, T&) {
    return [](T& x, T& y) { return swap(x, y); };
}

For instance, the following code:

namespace a {

  struct b {
      int i;
  };

  void swap(b& x, b& y) {
      std::swap(x.i, y.i);
  }
}

int main() {

    auto f0 = (void (*)(a::b&, a::b&)) a::swap;
    auto f1 = get_swap<a::b>();

    std::cout << std::hex;
    std::cout << (unsigned long long) f0 << '\n';
    std::cout << (unsigned long long) f1 << '\n';
}

compiled with gcc 4.8.1 (`-std=c++11 -O3`) on my machine gave:

4008a0
4008b0

The relevant assembly code (`objdump -dSC a.out`) is

00000000004008a0 <a::swap(a::b&, a::b&)>:
  4008a0:   8b 07                   mov    (%rdi),%eax
  4008a2:   8b 16                   mov    (%rsi),%edx
  4008a4:   89 17                   mov    %edx,(%rdi)
  4008a6:   89 06                   mov    %eax,(%rsi)
  4008a8:   c3                      retq   
  4008a9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

00000000004008b0 <void (*get_swap<a::b>())(a::b&, a::b&)::{lambda(a::b&, a::b&)#1}::_FUN(a::b&, a::b&)>:
  4008b0:   8b 07                   mov    (%rdi),%eax
  4008b2:   8b 16                   mov    (%rsi),%edx
  4008b4:   89 17                   mov    %edx,(%rdi)
  4008b6:   89 06                   mov    %eax,(%rsi)
  4008b8:   c3                      retq   
  4008b9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

As one can see the functions pointed by `f0` and `f1` (located at `0x4008a0` and `0x4008b0`, respectively) are binary identical. The same holds when compiled with clang 3.3.

If the linker can do identical COMDAT folding (ICF), I guess, we can even get `f0 == f1`. (For more on ICF see this post.)

Problem

Is it possible to take the address of a function that would be found through ADL? For example: ``` template<class T> void (*get_swap())(T &, T &) { return & _________; // how do I take the address of T's swap() function? } int main() { typedef some_type T; get_swap<T>(); } ```

Original source

Related problems