2013-08-06 13 views
12

Czy można wziąć adres funkcji, która mogłaby zostać znaleziona przez ADL?Czy można wziąć adres funkcji ADL?

Na przykład:

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

Odpowiedz

3

Szczerze mówiąc, nie wiem, ale mam tendencję do stwierdzenia, że ​​to nie jest możliwe.

W zależności od tego, co chcesz osiągnąć, mogę zasugerować obejście tego problemu. Dokładniej, jeśli wystarczy adres funkcji, która ma tą samą semantykę jak swap zwane przez ADL można użyć to:

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

Na przykład, następujący kod:

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

skompilowany z gcc 4.8.1 (-std=c++11 -O3) na moim komputerze dał:

4008a0 
4008b0 

Kod istotne montaż (objdump -dSC a.out) jest

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) 

Jak widać funkcji wskazanych przez f0 i f1 (znajduje się na 0x4008a0 i 0x4008b0, odpowiednio) są binarnie identyczne. To samo dotyczy kompilacji z klangiem 3.3.

Jeśli linker może wykonać identyczne składanie COMDAT (ICF), myślę, że możemy nawet uzyskać f0 == f1. (Więcej informacji o ICF zobaczyć this post.)

+0

[Cóż, przechodzi wszystkie moje testy] (http://coliru.stacked-crooked.com/view?id=46999fdc4c98b2092415c91172d44b12-cc73e281b3b6abc9bf6cf4f153b944a6) –

Powiązane problemy