Dato il seguente pezzo di codice:Compile tempo della spedizione: subordinata valido chiamata
template<typename GroupA, typename GroupB>
class JoinedObjectGroup
: public _ObjectSpaceHolder<GroupA>
, public _ObjectSpaceHolder<GroupB>
{
public:
JoinedObjectGroup(GroupA &groupA, GroupB &groupB)
: _ObjectSpaceHolder<GroupA>(groupA)
, _ObjectSpaceHolder<GroupB>(groupB)
{
}
template<typename ObjectType>
ObjectType get()
{
// Dispatch to appropriate handler: only one of the following actually compiles as
// either GroupA knows about ObjectType or GroupB, but not both. So:
//
// return static_cast<_ObjectSpaceHolder<GroupA> &>(*this).m_objectSpace.get<ObjectType>();
// or
// return static_cast<_ObjectSpaceHolder<GroupB> &>(*this).m_objectSpace.get<ObjectType>();
}
};
Nella chiamata get()
, vorrei eseguire un tempo della spedizione di compilazione al gestore appropriato. L'idea di base è che ObjectType
è noto o per GroupA
o per GroupB
. Il mio approccio iniziale era la seguente:
template<typename ObjectType>
ObjectType get()
{
return Dispatch<ObjectType, GroupA, GroupB>::get(*this);
}
con:
template<typename ObjectType, typename GroupA, typename GroupB, typename = void>
struct Dispatch;
template<typename ObjectType, typename GroupA, typename GroupB>
struct Dispatch<ObjectType, GroupA, GroupB, typename std::enable_if<std::is_same<ObjectType, decltype(std::declval<GroupA>().template get<ObjectType>())>::value>::type>
{
template<typename JoinedGroup>
static
ObjectType get(JoinedGroup &joinedGroup)
{
return static_cast<_ObjectSpaceHolder<GroupA> &>(joinedGroup).m_objectSpace.get<ObjectType>();
}
};
template<typename ObjectType, typename GroupA, typename GroupB>
struct Dispatch<ObjectType, GroupA, GroupB, typename std::enable_if<std::is_same<ObjectType, decltype(std::declval<GroupB>().template get<ObjectType>())>::value>::type>
{
template<typename JoinedGroup>
static
ObjectType get(JoinedGroup &joinedGroup)
{
return static_cast<_ObjectSpaceHolder<GroupB> &>(joinedGroup).m_objectSpace.get<ObjectType>();
}
};
Avevo pensato che avrebbe funzionato a pensare che sostituendo ObjectType
nella clausola is_same
di enable_if
porterebbe una delle espressioni a fallire e lasciando quindi solo una singola specializzazione valida. Tuttavia, nomi ambigui e errori di ridefinizione mi dimostrano un errore.
Perché il mio ragionamento è errato? E come posso inviare correttamente la chiamata?
@JoachimPileborg: Grazie, è stato introdotto un errore di battitura durante la semplificazione dei nomi. Risolto questo. – OnMyLittleDuck
Nota anche che '_ObjectSpaceHolder' è riservato al compilatore (insieme a tutti i nomi che iniziano con il carattere di sottolineatura-lettera maiuscola). –
Immagino che l'ipotesi di cui sopra sia che solo uno dei 'template T GroupA :: get ()' e 'modello T GroupB :: get ()' esiste - è proprio vero? –
Smeeheey