Я пишу универсальный класс-обертку для группы классов, которые мы определили в другом коде. Я пытаюсь выяснить, есть ли способ в C ++ написать шаблонный класс, который может хранить параметр шаблона в виде переменной. Вот пример того, что я хотел бы видеть на работе:
template < class C > class generic {
public:
C obj; // used for custom type processing
template < class T > T other; // <- changeable variable (or something)
template < class T > setOther() { // Function to change variable
// code to change variable type, or set type
}
void doSomethingWithOther() {
// do some processing for other, like call
// specific member function or something
(((other*)obj)->*SomeGenericMethod)()
}
}
int main(int argc, char **argv) {
Bar bObj;
generic<Foo> fObj;
fObj.setOther<Bar>();
fObj.doSomethingWithOther();
return 0;
}
Я знаю, что приведенный выше код не будет компилироваться по многим причинам, но мой вопрос больше касается функциональности. Есть ли какой-нибудь способ, которым я мог бы сохранить параметр шаблона как переменную (или использовать функцию или что-то), который затем мог бы использоваться позже как спецификатор типа? Если нет стандартного способа, какие-нибудь идеи от сообщества SO, которые могли бы привести к моим желаемым результатам?
Пожалуйста, не используйте Boost или другие сторонние библиотеки, я стараюсь сохранить его как "STL" (C99).
Другая идея, которая у меня возникла, заключалась в использовании специализаций по умолчанию:
template < class C, class T = void* > class generic {
public:
C obj;
T other;
// ... more code
}
но в этом случае, предполагая, что у нас было следующее:
class Test1 {
public:
generic<Foo> *G1;
generic<Foo, Bar> *G2;
};
Если бы я захотел позже изменить тип G1 для выполнения какой-либо другой обработки, я мог бы сказать что-то вроде следующего:
G1 = new generic<Foo, Bar>(); // compile error, different types
Однако это приведет к ошибке компиляции, поскольку указанные два типа имеют разные типы (G1 имеет тип generic< C >
, другой тип generic< C, T >
, хотя класс шаблона T
по умолчанию равен void*
.
Извините за длинный пост, я пытаюсь быть максимально понятным в своих намерениях с этим кодом. Также, пожалуйста, не стесняйтесь поправлять меня в любом из моих утверждений выше (долгие дни = меньше активности мозга для меня)
Заранее благодарим за любую помощь в этом вопросе.
Редактировать 1:
Для пояснения, элемент данных other
просто показывает, что я хотел бы, чтобы этот элемент содержал тип класса. Это связано с тем, что в нашем коде есть члены других классов, вызывающих инстансированные функции-члены. И если я сделаю вызов функции-члена другого класса, я получу ошибку компиляции.
И, к сожалению, я не могу использовать какие-либо функции C ++ 0x, поскольку наши встроенные компиляторы устарели и не поддерживают набор функций 0x. В противном случае это было бы очевидным решением.
По сути, мне нужно встроить систему делегированного типа, чтобы экземпляры классов могли вызывать члены других экземпляров классов изнутри себя, а вызываемая функция-член будет иметь пространство памяти и доступ к указателю this
.
Пример:
class Foo {
public:
Delegate other;
}
class Bar {
public:
void SomeFunction() {
std::cout << "hello from Bar::SomeFunction, data = " << data << std::endl;
}
int data;
}
int main() {
Foo F;
Bar B;
B.data = 10;
F.other = Delegate::attach<Bar>(&Bar::SomeFunction, &B);
// Delegate::attach is defined as
// template < class T > Delegate attach(void (T::*fnPtr)(void*), T *obj)
F.other();
}
В приведенном выше примере void operator()()
класса Delegate
затем вызывает функцию других членов через (*fnPtr)()
. Если вызывается таким образом, функция не имеет доступа к данным своего члена (не знает указатель this
). Если вызывается с передачей ссылочного объекта (т.е. (*fnPtr)(obj)
), функция теперь имеет доступ к данным члена.
Я пытаюсь решить эту проблему, указав универсальный объект class type
, который затем можно приводить туда-сюда, так как Delegate other
может присоединиться к любому члену.