2013-08-06 11 views
12

È possibile prendere l'indirizzo di una funzione che verrebbe trovata tramite ADL?È possibile prendere l'indirizzo di una funzione ADL?

Ad esempio:

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

risposta

3

Onestamente, non lo so, ma io tendo verso dicendo che questo non è possibile.

A seconda di ciò che si desidera ottenere, posso suggerire una soluzione alternativa. Più precisamente, se avete solo bisogno l'indirizzo di una funzione che ha la stessa semantica swap chiamati attraverso ADL, allora è possibile utilizzare questo:

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

Per esempio, il seguente codice:

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

compilato con gcc 4.8.1 (-std=c++11 -O3) sulla mia macchina ha dato:

4008a0 
4008b0 

Il relativo codice assembly (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) 

Come si può vedere le funzioni puntata da f0 e f1 (situata 0x4008a0 e 0x4008b0, rispettivamente) sono binari identici. Lo stesso vale quando compilato con clang 3.3.

Se il linker può fare identico COMDAT pieghevole (ICF), immagino, possiamo anche ottenere f0 == f1. (Per ulteriori informazioni su ICF vedere this post.)

+0

[Bene, passa tutti i miei test] (http://coliru.stacked-crooked.com/view?id=46999fdc4c98b2092415c91172d44b12-cc73e281b3b6abc9bf6cf4f153b944a6) –

Problemi correlati