Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Наследование частично специализированного шаблона


Автор: georain 31.1.2008, 11:25
Есть класс - шаблон с двумя специализациями
Другой класс - шаблон  наследует одну из специализаций в зависимости от своих параметров
Неспециализированный класс не определён

В нижеприведённом коде члены класса base не декларированы в классе derived, почему? 
(то что специализации почти одинаковые не обращайте внимания, это сделано для упрощения приведённого кода)

(компиляторы gcc4.1 и icc10.0)

Код

    // шаблон для специализации (пустой)
    template<typename Type, typename Date, bool>
    class base;

    // специализация если sizeof(Type) >= sizeof(Date)
    template<typename Type, typename Date>
    class base<Type, Date, false>
    {
        public:
        Type type;
        Date date;

    };

    // специализация если sizeof(Type) < sizeof(Date)
    template<typename Type, typename Date>
    class base<Type, Date, true>
    {
        public:
        Date date;
        Type type;
    };

template<typename Type, typename Date>
class derived: public base<Type, Date, (sizeof(Type) < sizeof(Date))> {
    public:
        inline const Date & getDate(){
            return date;
        };
        inline const Date & getType(){
            return type;
        };
};

Автор: Lazin 31.1.2008, 12:24
а ты вместо
Код

    // шаблон для переспециализации (пустой)
    template<typename Type, typename Date, bool>
    class base{
        //конструктор в секции private
        private: base(){};
        //этот класс не должен создаваться
    };


напиши
Код

    // шаблон для переспециализации (пустой)
    template<typename Type, typename Date, bool>
    class base;

Автор: georain 31.1.2008, 12:42
Неа, не помогает. Тоже самое.

Автор: Lazin 31.1.2008, 12:49
visual studio 8 это компилирует на ура..
что пишет компилятор?

Автор: archimed7592 31.1.2008, 13:13
14.6.2/3
Цитата

In the definition of a class template or a member of a class template, if a base class of the class template
depends on a template-parameter, the base class scope is not examined during unqualified name lookup
either at the point of definition of the class template or member or during an instantiation of the class template
or member.

Нужно this->type/base::Type.

Добавлено через 1 минуту и 50 секунд
Цитата(Lazin @  31.1.2008,  12:49 Найти цитируемый пост)
visual studio 8 это компилирует на ура..

MSVC плохо соответствует Стандарту... После него часть кода приходится переделывать :(.

Автор: georain 31.1.2008, 13:59
Точняк! archimed7592, вновь спасибо! smile

Надо перед всеми переменными поставить
Код

base<Type, Date, (sizeof(Type) < sizeof(Date))>::

или
Код

this->

Автор: archimed7592 31.1.2008, 16:46
Цитата(georain @  31.1.2008,  13:59 Найти цитируемый пост)
Надо перед всеми переменными поставить

Лучше сделать typedef ... Base; в class-scope(со спецификатором доступа private).

Автор: null56 15.1.2009, 21:23
Это получается стандарт с++ и такой код будет переносим на любые компиляторы, соответствующие этому стандарту, включая вижуал студио?

И еще вопросик, данной утверждение относится только для наследования от шаблона?
Когда класс наследуется от обычного класса по стандарту необходимость явного указания базового класса или указателя this отпадает?

Код

template <class T>
class Base
{
    protected:
    T value;
}

template <class T>
class Child : public Base
{
 void myFunc() {this->value;}
}

Автор: Kallikanzarid 15.1.2009, 21:53
null56, в твоем коде много причин для не-компиляции smile

Автор: null56 15.1.2009, 22:54
Kallikanzarid, при чем тут мой код?

Вопрос стоит в обращении к переменным базового шаблонного класса и обычного... и как это верно делать по стандарту, а не МВС

Автор: vinter 16.1.2009, 08:10
ненужен там this

Автор: null56 16.1.2009, 10:02
без this, вот чего происходит
Код

template <class T>
class TBasePointer
{
    public:
        inline bool isNull() {return (m_pPointer == 0);}
        inline T * relinquish() {T * p_pointer = m_pPointer; m_pPointer = 0; return p_pointer;}
        //-
        bool operator !() {return isNull();}
        //-
        T * m_pPointer;
};

template <class T>
class TPointer :  public TBasePointer<T>
{
    public:
        TPointer() : TBasePointer<T>() {}
        TPointer(T * pPointer) : TBasePointer<T>(pPointer) {}
        //-
        void destroy() {if (!isNull()) {delete m_pPointer; m_pPointer = 0;}}
};


Вывод получаем
Код

/pointer.h:34: error: there are no arguments to ‘isNull’ that depend on a template parameter, so a declaration of ‘isNull’ must be available
./pointer.h:34: error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
./pointer.h:34: error: ‘m_pPointer’ was not declared in this scope


То есть обратиться можно только через явное указание базового класса, либо через this

Автор: null56 16.1.2009, 11:15
Цитата

Цитата(georain @  31.1.2008,  13:59 Найти цитируемый пост)
Надо перед всеми переменными поставить

Лучше сделать typedef ... Base; в class-scope(со спецификатором доступа private). 


а как это реализовать?

Автор: vinter 16.1.2009, 19:10
Цитата(null56 @  16.1.2009,  11:02 Найти цитируемый пост)
Вывод получаем

VS2008 собирает

Автор: UnrealMan 16.1.2009, 19:42
Цитата(vinter @  16.1.2009,  19:10 Найти цитируемый пост)
VS2008 собирает 

Вывод: VC++ нарушает стандарт.

Код
#include <iostream>

enum { value = 1 };

template <class T>
struct B
{
    enum { value = 2 };
};

template <class T>
struct D : B<T>
{
    static void f() { std::cout << value << std::endl; }
};


int main()
{
    D<void>::f();
}

Стандарт требует, чтобы такая программа выводила 1, а не 2.

Автор: georain 23.1.2009, 19:54
Цитата(null56 @  16.1.2009,  11:15 Найти цитируемый пост)
а как это реализовать? 

Код

template<typename Type, typename Date>
class derived: public base<Type, Date, (sizeof(Type) < sizeof(Date))> {

    typedef   base<Type, Date, (sizeof(Type) < sizeof(Date))>   Base;

    public:
        const Date & getDate(){
            return Base::date;
        };
        const Date & getType(){
            return Base::type;
        };
};

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)