2012-10-12 106 views
8

vinculación lenguaje de Una función es parte de su tipo:¿Es posible especializar una plantilla en el enlace del idioma?

7.5.1 [dcl.link] de la ISO C++ estándar:

La vinculación idioma por defecto de todos los tipos de función, nombres de función, y variables names es un enlace de lenguaje C++. Dos tipos de funciones con enlaces de idiomas diferentes son tipos distintos, incluso si son idénticos.

¿Es posible especializar una plantilla en el tipo de vinculación de un puntero a función, o si no introspeccionar el tipo de un puntero a función para determinar su vinculación en tiempo de compilación?

Este primer intento no parece legal:

#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 salidas:

$ 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’ 

¿Hay alguna aplicación de SFINAE que podrían implementar esta funcionalidad?

Respuesta

7

Sí, creo que debería ser capaz de especializar una plantilla en función de su enlace de idioma según el estándar C++. He probado el código siguiente con el Comeau compiler online y compilado sin errores:

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

Sin embargo, creo que due to a gcc bug, gcc no distingue los tipos de función basada en la vinculación del lenguaje, así que esto no es posible con gcc (y no parece seguro cuando arreglarán esto).

+1

¿Tiene quizás una cita de la especificación que dice que la vinculación es parte de la información de tipo sobre la que se basan las plantillas de C++? –

+4

@NicolBolas: No, yo no. Sin embargo, creo que la cita en la pregunta es clara: 'Dos tipos de funciones con diferentes enlaces de idiomas son tipos distintos'. Y a partir de [14.4 Tipo de equivalencia]: 'Dos ID de plantilla se refieren a la misma clase o función si sus correspondientes argumentos tipo plantilla son del mismo tipo'. –

+1

@NicolBolas: eso sería 7.5.1 citado en la pregunta ... –

Cuestiones relacionadas