У меня есть следующий шаблон
template<typename T> void f(T t) { }
И я хочу передать адрес конкретной специализации его функции C
g(&f<int>);
Но поскольку я хочу быть переносимым, я хочу, чтобы вызывающее соглашение "f" соответствовало коду C. Поэтому я экспериментировал с тем, как языковая связь влияет на соглашение о вызове и обнаруживает
- Языковая связь типа функции влияет на соглашение о вызовах для использования
- Языковая связь имени функции влияет на mangling
В разделе ссылок на язык спецификации С++ указано
В спецификации привязки специфицированная языковая связь применяется к типам функций всех деклараторов функций, имен функций с внешней привязкой и именам переменных с внешней связью, объявленной в спецификации привязки.
Таким образом, чтобы предотвратить отключение манипуляции, которое необходимо для шаблонов, чтобы отличать разные специализации друг от друга в объектном файле, я сделал следующее.
extern "C" {
/* function name will not be affected */
template<typename T> static void f(T t) { }
}
Но это дает мне ошибку компилятора, говоря, что шаблоны не могут иметь ссылку на C-язык, что я подразумеваю, что он жалуется на тип функции шаблона функции. И фактически, я нашел спецификацию, чтобы сказать
Шаблон, явная специализация шаблона (14.7.3) и частичная специализация шаблона класса не должны иметь C-ссылки
Теперь мне кажется очевидным, что мы не хотим менять привязку имен, потому что мы полагаемся на mangling для работы. Но в чем причина запрета на изменение типа связи? Кажется, это ограничивает необходимость использования соглашения о вызовах на С++; кто-то знает причину, и есть ли легкая работа для достижения моей первоначальной цели?
Я изменил способ, которым я пытаюсь дать привязку только к типу сейчас, следующим образом
extern "C" typedef void ftype(int);
template<typename T>
ftype f;
И это прекрасно работает. К сожалению, я не вижу способа определить f
при использовании этой техники. Но, во всяком случае, ни один компилятор, который я пробовал, не поставил диагноз (попробовал EDG/comeau, GCC и clang), хотя это выглядит как та же ситуация, что и раньше: имя не должно связываться с языком C, но только тип имеет.
Кто-нибудь может это объяснить?