Возможное менее совершенное решение моего собственного вопроса:
1. Не беспокойтесь о методах и используйте вместо этого отдельно стоящие функции.
struct CoreData
{
int m_x;
~CoreData();
};
void TeamA_init(CoreData& data);
void TeamA_push_back(CoreData& data, Whatever args);
Iter TeamA_begin(CoreData& data);
bool TeamB_init(CoreData& data, Other args);
bool TeamB_push_back(CoreData& data, Whatever args);
X* TeamB_begin(CoreData& data);
//--------------------- Usage:
void ServiceOfTeamA::CallServiceOfTeamB(ServiceOfTeamB* srv)
{
CoreData d;
TeamA_init(d);
srv->Process(&d);
TeamA_begin(d);
}
void ServiceOfTeamB::Process(CoreData* d)
{
TeamB_push_back(*d, 567);
}
- Что мне не нравится в этом подходе, так это недружественный синтаксис, никакой RAII и все члены данных не являются открытыми. Это C, а не C ++.
+ С другой стороны, этот подход предлагает неограниченные возможности настройки. Нет ограничений в выборе правильной функции для задачи. Никаких накладных расходов на память, никаких накладных расходов на выполнение (то есть, технически компилятор имеет те же возможности вставки и оптимизации, что и методы, которые эти свободные функции будут использовать).
Возможное менее совершенное решение моего собственного вопроса:
3. Бросьте код на милость де-факто определенного поведения reinterpret_cast.
// This is a standard layout class.
// It is the only class with data members;
// derived classes never append new data members.
class CoreData
{
public:
// Could be either explicit conversion function
// or implicit conversion operator.
template <typename Final>
// requires <LayoutCompatibleWithCore Final>
Final& As()
{
return reinterpret_cast<Final&>(*this);
}
protected:
~CoreData();
int m_x;
};
// No extra data members appended. No extra invariants imposed.
// This class is also a standard layout type,
// fully layout-compatible with CoreData.
class TeamA : public CoreData
{
public:
void push_back(Whatever args);
Iter begin();
};
class TeamB : public CoreData
{
public:
bool push_back(Whatever args);
X* begin();
};
//--------------------- Usage:
void ServiceOfTeamA::CallServiceOfTeamB(ServiceOfTeamB* srv)
{
TeamA d;
srv->Process(&d);
d.begin();
}
void ServiceOfTeamB::Process(CoreData* core)
{
TeamB& d = core->As<TeamB>();
d.push_back(567);
}
- Однако такие приемы запрещены стандартом. Поэтому я тоже должен отказаться от этого подхода.
+ Если бы это было законно, он предложил бы лучший синтаксис из трех, синтаксис, четко показывающий эталонную семантику, с RAII и без пессимизации.
P.S. Недействительность такого подхода опускает меня. Весь смысл совместимости компоновки дает возможность передавать данные между ABI-совместимыми процессами или общими компонентами. Жаль, что это не позволяет передавать данные между частями одного и того же приложения ...