I have a templated class, Foo :
template <class A, class B>
class Foo
{
public:
Foo(A &aInstance);
private:
Attr<Foo> _attr;
};
Then I have another templated class called Attr which is an attribute of my Foo class and which takes as template parameter the Foo class itself.
template <class C>
class Attr
{
class SomeType
{
SomeType();
~SomeType();
};
Attr(const SomeType* st);
~Attr();
private:
Attr();
}
I want to init _attr (of type Attr) in the constructor, casting the first parameter from the template as SomeType.
Foo constructor implementation :
template&开发者_JAVA百科lt;class A, class B>
Foo<A, B>::Foo(A &aInstance):
_attr(
(Attr<Foo<A, B> >::SomeType *) aInstance)
{
}
This won't compile :
error: expected primary-expression before ')' token
That error refers to the cast line in the Foo contructor implementation, as if SomeType was not recognized.
I now have an instance, but still got the same error.
template<class A, class B>
Foo<A, B>::Foo():
_attr(
(Attr<Foo<A, B> >::SomeType *) A)
{
}
A
is a type, and you're trying to pass it to constructor. You need an instance here.
0)
(Attr<Foo<A, B> >::SomeType *) A)
at that point, A
is a typename, i.e. the name of a type, thus, not anything you can cast.
1)
Also, Foo<A,B>
is dependent upon A
and B
, therefore, Attr<Foo<A, B> >
is a dependent name, too. Hence, you need a typename
there so as to tell the compiler that SomeType
is a type:
(typename Attr<Foo<A, B> >::SomeType *) somePointer)
2)
Furthermore, in C++, generally prefer C++-casts over C-style-casts. You'll catch a lot of mistakes with them. See also this tutorial :)
3)
On the other hand: Are you sure you need the cast by design, or should Attr
point to exactly a Foo<A, B>
?
First of all, the Attr class does not (in your snippet) use the C type, so you should explain where it is used, and what is the relation between C and SomeType.
Second, in this lines
Foo<A, B>::Foo():
_attr(
(Attr<Foo<A, B> >::SomeType *) A)
A is a type and not an object. If _attr should be initialized with the Foo object itself, then you should pass pointer this.
Foo<A, B>::Foo():
_attr(
(Attr<Foo<A, B> >::SomeType *) this)
However, that this point, the Foo object is not yet constructed, so beware what you do with the pointer in the Attr constructor.
Try changing your constructor to:
template<class A, class B>
Foo<A, B>::Foo(A &aInstance):
_attr(
(typename Attr<Foo<A, B> >::SomeType *) &aInstance) {}
You will, because you want a pointer, need to add an address-of operator in order to take the address of the instance object ... otherwise aInstance
will not a pointer-type, instead it will be reference type which is effectively the same as passing the object itself (by reference), rather than a pointer to the object.
This works for me. A couple of typedefs help in making sense of templated code a little easier:
template<class C>
class Attr
{
public:
class SomeType
{
SomeType();
~SomeType();
};
typedef typename Attr<C>::SomeType ReachIntoSomeType;
Attr(const SomeType* st) { }
~Attr() { }
private:
Attr();
};
template <class A, class B>
class Foo
{
public:
Foo(A &aInstance) : _attr(reinterpret_cast<AttrOfFoo::ReachIntoSomeType*>(aInstance))
{ }
private:
typedef Attr<Foo> AttrOfFoo;
AttrOfFoo _attr;
};
精彩评论