Hello Martin MacRobert,
Martin MacRobert schrieb:
[color=blue]
>Hi Gang,
>The following code does not compile, but I can't figure out why. The
>compiler complains that the CuriouslyDerivedType (CRDerived) does not
>publish the "value_type", yet in fact the class CRDerived does.
>
>Is there any way of making the code work? I would like functions to
>accept a CRBase template, and the CRBase must be able to deduce the
>"value_type" of the function that it is "curiously calling".
>
>Thanks.
>Martin
>
>------snip here 8< ------
>template <typename CurioslyDerivedType>
>struct CRBase
>{
> typedef typename CurioslyDerivedType::value_type value_type;
>
> const CurioslyDerivedType& derived() const
> {
> return static_cast<const CurioslyDerivedType&>(*this);
> }
>
> value_type invoke() const
> {
> return derived().foo();
> }
>};
>
>struct CRDerived:
> public CRBase< CRDerived >
>{
> typedef int value_type;
>
> int foo() const
> {
> return 1234;
> }
>};
>
>template <typename CurioslyDerivedType>
>typename CRBase<CurioslyDerivedType>::value_type
>invoke(const CRBase<CurioslyDerivedType>& c)
>{
> return cr.invoke();
>}
>
>int main()
>{
> CRDerived c;
> int result = invoke(c);
> return 0;
>}
>
>
>------snip here 8< ------
>[/color]
The compiler is right, because CRDerived is still undefined at the point
of the definition of
the class CRBase. If you want to take advantage of CRTP you are limited
to uses of the
derived class which don't need its actual definition, e.g. inside member
functions. One
possibility is to move the static assertion into a member function of
CRBase, which **must**
be defined:
template <typename CurioslyDerivedType>
struct CRBase
{
~CRBase() {
typedef typename CurioslyDerivedType::value_type value_type;
}
..
};
Regrettably this does not help you in case of your member function:
value_type invoke() const;
The only workaround for this seems to be a further template parameter:
template <typename CurioslyDerivedType, typename ValueTypeT>
struct CRBase
{
typedef ValueTypeT value_type;
~CRBase() {
// This test ensures, that
// - CurioslyDerivedType provides a value_type name
// - that CurioslyDerivedType::value_type is identical to ValueTypeT
BOOST_STATIC_ASSERT(boost::is_same<typename CurioslyDerivedType::value_type, value_type>::value);
}
};
struct CRDerived:
public CRBase< CRDerived, int >
{
typedef int value_type;
int foo() const
{
return 1234;
}
};
Greetings from Bremen,
Daniel Krügler
[ See
http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]