Стандарт C++ в отношении внешней связи и соглашений о вызовах

Я прочитал последний черновик C++11 (n3337 — он последний?), и у меня возник вопрос о возможной реализации, над которой я работаю.

Допустим, у нас есть этот код:

extern "Objective C" {
  class Object {
    public:
      static Object *alloc();
      Object *init();
  };
};

Затем вызов

Object *x = Object::alloc()->init();

Вопрос в том, что я не понял, разрешено ли компилятору управлять соглашением о вызовах блоков extern "X": идея заключалась бы в том, чтобы "перевести" вызовы в objc_msgSend(blablabla) - будет ли это соответствовать стандартным, или это будет считаться расширением (поскольку оно не просто изменит имя символа, но и будет сложным «соглашением о вызовах»)? Конечно, я мог бы реализовать это, создав слабую функцию, которая вызывается как __thiscall, а затем вызывает и возвращает сам метод, но остается вопрос, будет ли он соответствовать?

Спасибо!


person paulotorrens    schedule 31.01.2013    source источник
comment
N3485.   -  person chris    schedule 31.01.2013
comment
Спасибо! Я только что скачал его. Но я все еще не знаю, будет ли такое поведение конформным.   -  person paulotorrens    schedule 31.01.2013
comment
Я понятия не имею. Я не имел ничего общего с obj-c. Я просто подумал, что вы оцените черновик обновления.   -  person chris    schedule 31.01.2013
comment
Вы прочитали черновик полностью? Вы, должно быть, уже запутались!   -  person David Rodríguez - dribeas    schedule 31.01.2013


Ответы (1)


Все, что вы описываете, звучит так, чтобы соответствовать цели функции языковой привязки.

Члены класса специально исключены из "C" языковой привязки. Согласно примерам в стандарте (C++11 §7.5/4), типы указателей функций в объявлениях членов класса, объявлениях extern в любом контексте и объявлениях всех других функций наследуют окружающий блок extern "C" {}. Вы определяете языковую связь помимо "C", но было бы менее удивительно следовать ее примеру, возможно, с дополнительным сопоставлением между this и self.

Требования открыты, согласно §7.5/2:

Использование строкового литерала, отличного от "C" или "C++", поддерживается условно, с семантикой, определяемой реализацией. [Примечание: поэтому спецификация связи со строковым литералом, который неизвестен реализации, требует диагностики. — end note ] [Примечание: рекомендуется брать написание строкового литерала из документа, определяющего этот язык. Например, Ада (не АДА) и Фортран или ФОРТРАН, в зависимости от урожая. — примечание в конце]

Вы можете переключиться на совершенно другой язык в фигурных скобках, и все будет в порядке. (Хотя с точки зрения грамматики все должно анализироваться как declaration C++ или declaration-seq.)

Однако в соответствии с этим вы должны использовать extern "Objective-C" с дефисом, поскольку окончательное название документа — «Язык программирования Objective-C».

EDIT: Безусловно, вызов через objc_msgSend не влияет ни на что, указанное в стандарте. Нигде не сказано, как вызываются функции C++. Добавленная промежуточная функция - это просто инструкции машинного уровня, выходящие за рамки языковой семантики, и ничем не отличаются от специальных инструкций, используемых для вызова Pascal, Fortran и т. д., например. путем изменения порядка параметров в стеке. Я не хочу сравнивать вашу схему с «переключением на совершенно другой язык в фигурных скобках», просто чтобы подчеркнуть, что запаса хватает.

Взяв в качестве примера спецификацию extern "C" в стандарте, она ломает много вещей, коренным образом изменяя правило ODR, потому что C не обязан поддерживать какое-либо искажение. Таким образом, ваша схема может нарушить как минимум столько.

person Potatoswatter    schedule 31.01.2013
comment
Содержимое класса исключается только при наличии связи C в соответствии со стандартом. :) - person paulotorrens; 31.01.2013
comment
@PauloTorrens Так и есть. Исправлю ответ. - person Potatoswatter; 31.01.2013
comment
Спасибо за ответ. Теперь мне нужно только подумать, как я должен отображать двоеточия, чтобы вы могли вызвать любое сообщение. :3 - person paulotorrens; 31.01.2013
comment
@PauloTorrens Три варианта: 1. Знаки @ и $ не используются, но во многих реализациях уже используются как буквы. (Я предполагаю, что вы строите на Clang, но это определенно стоит посмотреть.) 2. Двойное подчеркивание __ зарезервировано для системы, поэтому вы можете безопасно его использовать, хотя некоторые идиоты помещают подобные вещи в идентификаторы. 3. Вы можете расширить синтаксис аргумента функции для поддержки двоеточия; Я не понимаю, почему это не сработает. Хотя это, конечно, было бы несовместимым, это было бы очень хорошо, и это могло бы просто сопоставляться с одним из других вариантов. - person Potatoswatter; 31.01.2013
comment
На самом деле, это мой собственный проект black, сейчас я работаю над более простыми привязками между языками. Проблема в том, что я считаю Objective-C++ довольно уродливым. Я попытался использовать двоеточие, чтобы посмотреть, что скажут компиляторы, и поскольку все они жаловались на неправильную связь с Objective-C перед двоеточием... хотя я думаю, что было бы лучше сопоставить что-то. Может быть, используя [[атрибут]]? - person paulotorrens; 31.01.2013
comment
@PauloTorrens Круто. Взгляните на мой проект code.google.com/p/c-plus , автономный препроцессор, который в основном является испытательным стендом для компилятора C++11. Я бы не рекомендовал [[attribute]]; это будет утомительно. Не уверен, что вы тестировали на других компиляторах, но вы можете условно #define objc "Objective-C". Вы можете взять неиспользуемые имена из предварительных объявлений. Вы можете что-то перепутать, чтобы использовать именованные инициализаторы и фигурные скобки C99 для самого вызова функции а-ля инициализация фигурной скобки. - person Potatoswatter; 31.01.2013