Языковая связь функции является частью ее типа:
7.5.1 [dcl.link] стандарта ISO C ++:
Языковая связь по умолчанию для всех типов функций, имен функций и имен переменных — это языковая связь C ++. Два типа функций с разными языковыми связями являются разными типами, даже если они идентичны.
Можно ли специализировать шаблон на типе связи указателя функции или иным образом анализировать тип указателя функции для определения его связи во время компиляции?
Эта первая попытка не кажется законной:
#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
выходы:
$ 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’
Есть ли какое-нибудь приложение SFINAE, которое могло бы реализовать эту функцию?
Да, я считаю, что вы должны иметь возможность специализировать шаблон на основе его языковой связи в соответствии со стандартом C ++. Я проверил следующий код с Comeau компилятор онлайн и скомпилировано без ошибок:
#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;
}
Тем не менее, я считаю, что из-за ошибки в gcc, gcc не различает типы функций по языковым связям, поэтому это невозможно с gcc (и неясно, когда они это исправят).
Других решений пока нет …