C ++ шаблонный класс и init в конструкторе - PullRequest
0 голосов
/ 07 июля 2011

У меня есть шаблонный класс, Foo:

template <class A, class B>
class Foo
{
public:
    Foo(A &aInstance);

private:
    Attr<Foo> _attr;
};

Затем у меня есть другой шаблонный класс, называемый Attr, который является атрибутом моего класса Foo и который принимает в качестве параметра шаблона сам класс Foo.

template <class C>
class Attr
{
    class SomeType
    {
        SomeType();
        ~SomeType();
    };

    Attr(const SomeType* st);
    ~Attr();

private:
    Attr();
}

Я хочу инициализировать _attr (типа Attr) в конструкторе, приведя первый параметр из шаблона как SomeType.

Реализация конструктора Foo:

template<class A, class B>
Foo<A, B>::Foo(A &aInstance):
    _attr(
        (Attr<Foo<A, B> >::SomeType *) aInstance)
{

}

Это не скомпилируется:

ошибка: ожидаемое первичное выражение до маркера ')'

Эта ошибка относится к строке приведения в реализации конструктора Foo, как если бы SomeType не был распознан.

Теперь у меня есть экземпляр, но все еще появляется та же ошибка.

Ответы [ 5 ]

2 голосов
/ 07 июля 2011
template<class A, class B>
Foo<A, B>::Foo():
    _attr(
        (Attr<Foo<A, B> >::SomeType *) A)
{

}

A - это тип, и вы пытаетесь передать его конструктору.Вам нужен экземпляр здесь.

1 голос
/ 07 июля 2011

Прежде всего, класс Attr (в вашем фрагменте) не использует тип C, поэтому вы должны объяснить, где он используется и какова связь между C и SomeType.

Во-вторых, в этой строке

Foo<A, B>::Foo():
    _attr(
        (Attr<Foo<A, B> >::SomeType *) A)

A - это тип, а не объект. Если _attr должен быть инициализирован самим объектом Foo, тогда вы должны передать указатель this.

Foo<A, B>::Foo():
    _attr(
        (Attr<Foo<A, B> >::SomeType *) this)

Однако, этот момент, объект Foo еще не создан, поэтому будьте осторожны с тем, что вы делаете с указателем в конструкторе Attr.

1 голос
/ 07 июля 2011

0)

(Attr<Foo<A, B> >::SomeType *) A)

в этот момент, A - это имя типа, то есть имя типа, то есть не все, что вы можете разыграть.

1)

Кроме того, Foo<A,B> зависит от A и B, поэтому Attr<Foo<A, B> > также является зависимым именем.Следовательно, вам нужен typename, чтобы сообщить компилятору, что SomeType - это тип:

(typename Attr<Foo<A, B> >::SomeType *) somePointer)

2)

Кроме того, в C ++ обычно предпочитают C ++ - приведениенад C-style-casts.Вы поймете много ошибок с ними.См. Также этот учебник :)

3)

С другой стороны: Вы уверены, что вам нужен отливок по замыслу, или Attr должно указывать точно наFoo<A, B>

0 голосов
/ 07 июля 2011

Это работает для меня.Несколько typedefs помогают немного облегчить понимание шаблонного кода:

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;
};
0 голосов
/ 07 июля 2011

Попробуйте изменить конструктор на:

template<class A, class B>
Foo<A, B>::Foo(A &aInstance):
    _attr(
        (typename Attr<Foo<A, B> >::SomeType *) &aInstance) {}

Поскольку вам нужен указатель, вам нужно добавить оператор адреса для получения адреса объекта экземпляра ... в противном случае aInstance не будет указателем, вместо этого он будет ссылочным типом. что фактически означает передачу самого объекта (по ссылке), а не указателя на объект.

...