Oppure

Loading
09/06/16 12:29
TheDarkJuster
Buongiorno a tutti,
sto cercando (invano) di creare un sistema di reflection per il c++ che genera diverse informazioni a compile-time per le nuove classi dichiarate dal programmatore.

Ora.... Io voglio poter fare una cosa del genere...
sapendo che ogni classe su cui la reflection funziona eredita da ReflectableObject io voglio creare una funzione template che dato un tipo ne restitusce una istanza:
template <class T>
SeaDragon::ReflectableObject* createReflectableObject();

template <class T> SeaDragon::ReflectableObject* createReflectableObject() {
	return new SeaDragon::ReflectableObject();
}

L'errore del compilatore (MSVC) è: "dichiarazione/definizione di modello non riconoscibile".

Come potete notare non uso nemmeno il tipo passato come argomento di template: al compilatore da fastidio che il tipo di ritorno sia SeaDragon::ReflectableObject*.

Se uso void* tutto "funziona":
template <class T>
void* createReflectableObject();

template <class T> void* createReflectableObject() {
	return (void*)(new SeaDragon::ReflectableObject());
}


La domanda è questa: Cosa ha di sbagliato il codice sopra? Perchè al compilatore crea così tanti problemi?
Dove sto sbagliando?

Questo codice è perfettamente valido:
template <class T>
void* createReflectableObject();

template <class T> void* createReflectableObject() {
	return (void*)(new T());
}

ma io voglio questo:
template <class T>
SeaDragon::ReflectableObject* createReflectableObject();

template <class T> SeaDragon::ReflectableObject* createReflectableObject() {
	return (SeaDragon::ReflectableObject*)(new T());
}


perchè poi voglio fare:
Type::getType("nome del mio tipo";)->newInstanceWithoutArgs();

e newInstanceWithoutArgs() richiama il membro di classe Type:
SeaDragon::ReflectableObject* (*puntatoreAFunzioneCheCreaLaNuovaIstanza)();


in questo modo:
this->puntatoreAFunzioneCheCreaLaNuovaIstanza();


Ma tutto questo non sta in piedi se il compilatore non accetta di compilare una funzione template che ritorna ReflectableObject.
aaa
09/06/16 12:36
HeDo
Ti consiglio la lettura di questo topic su StackOverflow

stackoverflow.com/questions/41453/…
aaa
09/06/16 13:28
TheDarkJuster
Ho già letto quel topic diverse volte, la prima volta ne è anche nata una discussione su pierotofy.it (il topic dovrebbe avere qualche mese).

Al momento ho risolto senza problemi usando la funzione:
template <class T>
void* createReflectableObject();

template <class T> void* createReflectableObject() {
	return (void*)(new T());
}


e facendo uno static_cast da void* a ReflectableObject*, ma non capisco perchè il compilatore si rifiuti di compilare
template <class T>
ReflectableObject* createReflectableObject();

template <class T> ReflectableObject* createReflectableObject() {
	return (ReflectableObject*)(new T());
}


visto che poi non ha alcun problema a fare:

static_cast<ReflectableObject*>(this->constructWithoutArgs());


Non mi sembra un comportamento desiderabile.
aaa
10/06/16 17:55
lumo
Ci dev'essere qualche errore bastardo, potresti mettere una parte della dichiarazione di ReflectableObject? Non mi è ben chiaro cosa vuoi ottenere
aaa
10/06/16 18:23
TheDarkJuster
La classe ReflectableObject è vuota: non c'è niente.
Al momento della scrittura di quel codice era semplicemente fatta così:
namespace SeaDragon {
	namespace Reflection {
		class Type;

		class SEADRAGON_API ReflectableObject {
		    
		};
	}
}


Questa classe servirà per implementare proprietà utili alla reflection, ma al momento è completamente inutilizzata.

Comunque su GitHub: github.com/NeroReflex/…

Puoi vedere cosa voglio ottenere esattamente: github.com/NeroReflex/SeaDragon/blob/master/test/…

Se guardi l'ultimo test vedi che alla fine tutto è fatto per ottenere una istanza di Type da una stringa contenente il nome con cui è stato registrato il tipo.

SeaDragon::Reflection::ReflectionSystem::GetType(QUOTE(reflection_support));

si risolve in
SeaDragon::Reflection::ReflectionSystem::GetType("reflection_support");

e ciò è valido: il tipo è stato rgistrato poche righe sopra:
REGISTER_REFLECTABLE_TYPE(reflection_support);


reflection_support eredita da ReflectableObject, solo che al momento della scrittura della domanda ReflectableObject era vuota.
Ora c'è una funzione pubblica e un membro privato. La funzione ritorna il valore del membro privato.

Nient'altro. Non c'è modo di modificare il membro privato (che è li solo come antefatto di un esperimento).

In ogni caso.... vuota o non vuota la build fallisce, quindi attualmente registro una funzione che dato un tipo ne crea una nuova istanza e ritorna l'indirizzo iniziale come void*, la funzione newInstanceWithoutArgs() richiama quella funzione, fa un cast (nemmeno tanto semplice, visto che è un static_cast<ReflectableObject*>( ... ), e non un (ReflectableObject*)( ... )):

ReflectableObject* Type::newInstanceWithoutArgs() {
	return static_cast<ReflectableObject*>(this->newInstanceFunction());
}


Mi scoccia un po' dover fare il cast su newInstanceWithoutArgs, non è affatto elegante, ma a quanto pare il compilatore non mi permette i fare il altro modo.
aaa