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

亡梦爱人 提交于 2019-12-03 16:12:30

问题


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>();
}

回答1:


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.)



来源:https://stackoverflow.com/questions/18086861/is-it-possible-to-take-the-address-of-an-adl-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!