c++ - 是否可以获取 ADL 函数的地址?

标签 c++ function-pointers argument-dependent-lookup

是否可以获取通过 ADL 找到的函数的地址?

例如:

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

最佳答案

老实说,我不知道,但我倾向于说这是不可能的。

根据您想要实现的目标,我可以建议一种解决方法。更准确地说,如果您只需要与通过 ADL 调用的 swap 具有相同语义的函数的地址,那么您可以使用:

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

比如下面的代码:

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';
}

在我的机器上用 gcc 4.8.1 (-std=c++11 -O3) 编译得到:

4008a0
4008b0

相关的汇编代码(objdump -dSC a.out)是

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)

可以看到 f0f1 所指向的函数(分别位于 0x4008a00x4008b0 ) 是二进制相同的。使用 clang 3.3 编译时也是如此。

如果链接器可以进行相同的 COMDAT 折叠 (ICF),我猜,我们甚至可以得到 f0 == f1。 (有关 ICF 的更多信息,请参阅 this 帖子。)

关于c++ - 是否可以获取 ADL 函数的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18086861/

相关文章:

c - 在 C 中初始化包含函数指针的结构

c++ - 使用指向独立函数的指针调用 std::thread

c++ - 在 ADL 期间如何防止遮盖?

c++ - 如何在约束中使用 ADL?

c++ - else if 条件被忽略

c++ - 上下文菜单适用于子组件但不适用于父组件

c++ - 将函数指针保存在数组 C++ 中

c++ - 如何调用与成员函数同名的内联友元函数?

c++ - XML 文件格式中的 bool 值应该写成 true/false 还是 1/0?

c++ - 如何使用具有递归模板函数的线程