В чистом мире C ++ мы можем генерировать интерфейс или склеивать код между различными компонентами или интерфейсами во время компиляции, используя комбинацию основанных на шаблонах методов компиляции и времени выполнения (например, в большинстве случаев для автоматического маршалинга в / из звонки с использованием устаревших типов) .
При необходимости сопряжения приложений C ++ с Objective-C / Cocoa для графического интерфейса пользователя, системной интеграции или IPC все становится сложнее из-за менее строгой типизации, но зачастую не больше, чем необходим плоский интерфейс с повторяющимся интерфейсом: узкие мостовые делегаты должен быть определен или должен быть написан код преобразования в языковые мостовые вызовы.
Если вам приходится иметь дело с интерфейсами нетривиального размера и вы хотите избежать генерации кода на основе сценариев, это быстро становится громоздким и вызывает боль каждый раз, когда необходимо проводить рефакторинг. Используя комбинацию (шаблонного) метапрограммирования и библиотеки времени выполнения Objective C, можно значительно сократить объем кода ...
Прежде чем я начну изобретать велосипед (и, возможно, потрачу время) , кто-нибудь знает о методах, лучших практиках или примерах в этом направлении?
Как в примере, скажем, нам нужен делегат, который поддерживает этот неофициальный протокол:
- (NSString*)concatString:(NSString*)s1 withString:(NSString*)s2;
- (NSNumber*) indexOf:(CustomClass*)obj;
Вместо реализации класса Obj-C, который теперь явно связан с экземпляром C ++, я хотел бы сделать что-то вроде этого вместо этого:
class CppObj {
ObjcDelegate m_del;
public:
CppObj() : m_del(this)
{
m_del.addHandler
<NSString* (NSString*, NSString*)>
("concatString", &CppObj::concat);
m_del.addHandler
<NSNumber* (CustomClass*)>
("indexOf", &CppObj::indexOf);
}
std::string concat(const std::string& s1, const std::string& s2) {
return s1.append(s2);
}
size_t indexOf(const ConvertedCustomClass& obj) {
return 42;
}
};
Все, что может потребоваться пользователю для поддержки дополнительных типов, - это специализировать функцию шаблона преобразования:
template<class To, class From> To convert(const From&);
template<>
NSString* convert<NSString*, std::string>(const std::string& s) {
// ...
}
// ...
В приведенном выше примере, конечно, игнорируется поддержка формальных протоколов и т. Д., Но суть должна быть понятна. Кроме того, из-за того, что информация о типах для Objc-runtime-типов в основном распадалась на some-native-types или class-type , я не думаю, что явная спецификация параметра и возвращаемых типов для делегата- методов можно избежать.