2012-10-12 12 views
8

legame lingua di una funzione è parte del suo tipo:È possibile specializzare un modello sul collegamento linguistico?

7.5.1 [dcl.link] della norma ISO standard C++:

Il legame lingua di default di tutti i tipi di funzione, i nomi delle funzioni e variabili i nomi sono collegamenti linguistici C++. Due tipi di funzione con collegamenti linguistici diversi sono tipi distinti, anche se sono identici.

È possibile specializzare un modello sul tipo di collegamento di un puntatore a funzione o altrimenti analizzare il tipo di un puntatore a funzione per determinarne il collegamento in fase di compilazione?

Questo primo tentativo non sembra legale:

#include <iostream> 
#include <typeinfo> 

struct cpp {}; 
struct c {}; 

extern "C++" void foo() 
{ 
    std::cout << "foo" << std::endl; 
} 

extern "C" void bar() 
{ 
    std::cout << "bar" << std::endl; 
} 

template<typename> struct linkage; 

template<> 
    struct linkage<void(*)()> 
{ 
    typedef cpp type; 
}; 

template<> 
    struct linkage<extern "C" void(*)()> 
{ 
    typedef c type; 
} 


int main() 
{ 
    std::cout << "linkage of foo: " << typeid(linkage<decltype(&foo)>::type).name() << std::endl; 
    std::cout << "linkage of bar: " << typeid(linkage<decltype(&bar)>::type).name() << std::endl; 
    return 0; 
} 

g++-4.6 uscite:

$ g++ -std=c++0x test.cpp 
test.cpp:26:38: error: template argument 1 is invalid 
test.cpp:26:3: error: new types may not be defined in a return type 
test.cpp:26:3: note: (perhaps a semicolon is missing after the definition of ‘<type error>’) 
test.cpp:32:10: error: two or more data types in declaration of ‘main’ 

C'è qualche applicazione di SFINAE che potrebbe implementare questa funzionalità?

risposta

7

Sì, credo che dovresti essere in grado di specializzare un modello basato sul suo collegamento linguistico secondo lo standard C++. Ho provato il seguente codice con il Comeau compiler online e compilato senza errori:

#include <iostream> 
#include <typeinfo> 

struct cpp {}; 
struct c {}; 

extern "C++" typedef void(*cppfunc)(); 
extern "C" typedef void(*cfunc)(); 

extern "C++" void foo() 
{ 
    std::cout << "foo" << std::endl; 
} 

extern "C" void bar() 
{ 
    std::cout << "bar" << std::endl; 
} 

template<typename> struct linkage; 

template<> 
    struct linkage<cppfunc> 
{ 
    typedef cpp type; 
}; 

template<> 
    struct linkage<cfunc> 
{ 
    typedef c type; 
}; 


int main() 
{ 
    std::cout << "linkage of foo: " << typeid(linkage<decltype(&foo)>::type).name() << std::endl; 
    std::cout << "linkage of bar: " << typeid(linkage<decltype(&bar)>::type).name() << std::endl; 
    return 0; 
} 

Tuttavia, credo che due to a gcc bug, gcc non distingue tipi di funzione sulla base di linkage lingua, quindi questo non è possibile con gcc (e non sembra sicuro quando sistemeranno questo).

+1

Avete forse una citazione spec che dice che il collegamento è parte del tipo di informazioni su cui sono basati i modelli C++? –

+4

@NicolBolas: No, non lo so. Tuttavia, penso che la citazione nella domanda sia chiara: "Due tipi di funzione con collegamenti linguistici diversi sono tipi distinti". E da [14.4 Equivalenza di tipo]: 'Due id template si riferiscono alla stessa classe o funzione se i corrispondenti argomenti template tipo sono dello stesso tipo'. –

+1

@NicolBolas: sarebbe 7.5.1 citato nella domanda ... –

Problemi correlati