2013-08-06 27 views
12

Có thể lấy địa chỉ của một hàm sẽ được tìm thấy thông qua ADL không?Có thể lấy địa chỉ của một hàm ADL không?

Ví dụ:

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

Trả lời

3

Thành thực mà nói, tôi không biết nhưng tôi có xu hướng hướng tới nói rằng đây là không thể.

Tùy thuộc vào những gì bạn muốn đạt được, tôi có thể đề xuất giải pháp thay thế. Chính xác hơn, nếu bạn chỉ cần địa chỉ của một hàm có ngữ nghĩa giống như swap gọi qua ADL sau đó bạn có thể sử dụng này:

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

Ví dụ, đoạn mã sau:

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

biên soạn với gcc 4.8.1 (-std=c++11 -O3) trên máy tính của tôi đã cho:

4008a0 
4008b0 

mã lắp ráp liên quan (objdump -dSC a.out) là

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) 

Như người ta có thể thấy các chức năng được trỏ bởi f0f1 (tọa lạc tại 0x4008a00x4008b0, tương ứng) là nhị phân giống hệt nhau. Điều tương tự cũng được giữ khi biên dịch với clang 3.3.

Nếu mối liên kết có thể làm COMDAT giống hệt gấp (ICF), tôi đoán, chúng tôi thậm chí có thể có được f0 == f1. (Để biết thêm thông tin về ICF, hãy xem this bài đăng.)

+0

[Vâng, vượt qua tất cả các bài kiểm tra của tôi] (http://coliru.stacked-crooked.com/view?id=46999fdc4c98b2092415c91172d44b12-cc73e281b3b6abc9bf6cf4f153b944a6) –

Các vấn đề liên quan