Использование typedefs производного класса в базе
Я хочу, чтобы производный класс был потомком класса шаблона. Этот класс зависит от членов-потомков.
Короче говоря, я хочу, чтобы этот код компилировался:
struct IBootParams
{
virtual bool GetImmediate() = 0;
};
template <class T>
struct TBootBootParams
{
typename T::TransType transferType;
typename T::UseAbort_ useAbort;
bool GetImmediate()
{
if ( transferType == T::e1 )
{
return useAbort.someFlag;
}
return false;
}
};
struct BootBootParams : public TBootBootParams<BootBootParams>
{
enum SomeEnum
{
e1=0,
e2,
e3
};
struct UseAbort
{
bool someFlag;
char someMember;
int otherMember;
} useAbort;
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
struct BootAltBootParams : public TBootBootParams<BootAltBootParams>
{
enum SomeEnum
{
e1=5,
e2,
e3
};
struct UseAbort
{
bool someFlag;
long long someMember;
long long otherMember;
} useAbort;
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
int _tmain(int argc, _TCHAR* argv[])
{
BootBootParams bp;
BootAltBootParams bpa;
bool f = bp.GetImmediate();
f = bpa.GetImmediate();
}
Ответы
Ответ 1
Вы не можете этого сделать. Когда компилятор создает экземпляр TBootBootParams<BootBootParams>
, он еще не полностью прочитал все определение BootBootParams, поэтому вы не можете получить доступ к своим членам из определения TBootBootParams (функции-члены TBootBootParams являются исключением, поскольку они создаются позже).
Обычное решение состоит в том, чтобы иметь класс признаков:
template<class T> struct TBootBootParams_traits;
template <class T>
struct TBootBootParams
{
typename TBootBootParams_traits<T>::TransType transferType;
typename TBootBootParams_traits<T>::UseAbort_ useAbort;
bool GetImmediate()
{
if ( transferType == TBootBootParams_traits<T>::e1 )
{
return useAbort.someFlag;
}
return false;
}
};
struct BootBootParams;
template<> struct TBootBootParams_traits<BootBootParams>
{
enum SomeEnum
{
e1=5,
e2,
e3
};
struct UseAbort
{
bool someFlag;
long long someMember;
long long otherMember;
};
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
struct BootBootParams :
public TBootBootParams<BootBootParams>,
public TBootBootParams_traits<BootBootParams>
{
UseAbort_ useAbort;
};
Ответ 2
Нет никакого способа, которым это может работать, что не является чем-то вроде взлома. Итак, вот моя попытка немного взломать:
struct IBootParams
{
virtual bool GetImmediate() = 0;
};
template <class T>
struct TBootBootParams : public IBootParams
{
typename T::TransType transferType;
typename T::UseAbort_ useAbort;
virtual bool GetImmediate()
{
if ( transferType == T::e1 )
{
return useAbort.someFlag;
}
return false;
}
};
struct BootBootParams_types
{
enum SomeEnum
{
e1=0,
e2,
e3
};
struct UseAbort
{
bool someFlag;
char someMember;
int otherMember;
} useAbort;
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
struct BootBootParams : public BootBootParams_types,
public TBootBootParams<BootBootParams_types>
{
};
struct BootAltBootParams_types
{
enum SomeEnum
{
e1=5,
e2,
e3
};
struct UseAbort
{
bool someFlag;
long long someMember;
long long otherMember;
} useAbort;
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
struct BootAltBootParams : public BootAltBootParams_types,
public TBootBootParams<BootAltBootParams_types>
{
};
int main(int argc, const char * argv[])
{
BootBootParams bp;
BootAltBootParams bpa;
bool f = bp.GetImmediate();
f = bpa.GetImmediate();
}
Ответ 3
Это делает то, что вы хотите? Он компилируется.
struct IBootParams
{
virtual bool GetImmediate() = 0;
};
template <class T>
struct TBootBootParams
{
bool GetImmediate()
{
if ( static_cast<T*>(this)->transferType == T::e1 )
{
return static_cast<T*>(this)->useAbort.someFlag;
}
return false;
}
};
struct BootBootParams : public TBootBootParams<BootBootParams>
{
enum SomeEnum
{
e1=0,
e2,
e3
} transferType;
struct UseAbort
{
bool someFlag;
char someMember;
int otherMember;
} useAbort;
};
struct BootAltBootParams : public TBootBootParams<BootAltBootParams>
{
enum SomeEnum
{
e1=5,
e2,
e3
} transferType;
struct UseAbort
{
bool someFlag;
long long someMember;
long long otherMember;
} useAbort;
};
int main(void)
{
BootBootParams bp;
BootAltBootParams bpa;
bool f = bp.GetImmediate();
f = bpa.GetImmediate();
}
Ответ 4
Я попробовал небольшое изменение в решении ybungalobill, сославшись на мои собственные потребности. И это то, что я получил
template<class T>
struct TBootBootParams_traits;
template <class T>
struct TBootBootParams
{
typedef TBootBootParams_traits<T> Traits;
typename Traits::TransType transferType;
typename Traits::UseAbort_ useAbort;
bool GetImmediate()
{
if ( transferType == TBootBootParams_traits<T>::e1 )
{
return useAbort.someFlag;
}
return false;
}
};
struct BootBootParams;
struct BootAltBootParams;
template<>
struct TBootBootParams_traits<BootBootParams>
{
enum SomeEnum
{
e1=5,
e2,
e3
};
struct UseAbort
{
bool someFlag;
long long someMember;
long long otherMember;
};
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
template<>
struct TBootBootParams_traits<BootAltBootParams>
{
enum SomeEnum
{
e1=5,
e2,
e3
};
struct UseAbort
{
bool someFlag;
int someMember;
float otherMember;
};
typedef SomeEnum TransType;
typedef UseAbort UseAbort_;
};
struct BootBootParams :
public TBootBootParams<BootBootParams>
{
};
struct BootAltBootParams :
public TBootBootParams<BootAltBootParams>
{
};
int main(void)
{
BootBootParams bp;
BootAltBootParams bpa;
bool f = bp.GetImmediate();
f = bpa.GetImmediate();
}
Подводя итог.. Я использую класс шаблона как обязательный параметр другого класса для этого класса, размещая там все данные типа. Это то, что мне нужно. Еще раз спасибо за этот вариант!
Ответ 5
Для этого подхода к работе вы должны включить объект класса шаблона в качестве члена родительского класса.