Вложенные шаблоны gcc compiler 4.1.2 error

Я пытаюсь создать шаблонный класс, чтобы изолировать пользователей от типа данных. Я бы предпочел использовать класс адаптера, но для изменения сигнатуры функций требуется шаблон.

В приведенном ниже примере кода (это не настоящий проект, а просто упрощенная версия для иллюстрации проблемы), а в основной подпрограмме я могу использовать интерфейс ob_traits. Но когда я пытаюсь создать шаблонный StructWrapper, который использует ob_traits в качестве базового класса, я получаю ошибки, и gcc не распознает созданный класс IntAdapter. Это компилируется на MSVC 8.0, но не работает на gcc 4.1.2 20070626 (Red Hat 4.1.2-14)

Итак, сначала два вопроса: вы понимаете, почему компиляция не выполняется с ошибками, указанными ниже?

Во-вторых, есть ли предложения о том, как проще реализовать эту концепцию?

    #include <iostream>

    template <typename T >
    struct ob_traits
    {
        ob_traits( T& param ) { value = param; };
        T value;
    };

    struct GeneralStructure
    {
        int a;
        GeneralStructure(int param):a(param){}
    };

    struct DifferentStructure
    {
        GeneralStructure hidden;
        DifferentStructure( int param ):hidden(param){};
    }
    ;

    /*template< typename T > struct ob_traits
    {
    };
    */
    template<> struct ob_traits< GeneralStructure >
    {
        struct IntAdapter
        {
            IntAdapter( GeneralStructure& valueParam ):value(valueParam){}
            GeneralStructure value;
            int& getValue() { return value.a; };
        };
    };

    template<> struct ob_traits< DifferentStructure >
    {
        struct IntAdapter
        {
            IntAdapter( DifferentStructure& valueParam):value( valueParam ){}
            DifferentStructure value;
            int& getValue( ){ return value.hidden.a; };
        };
        void dump()
        {
            DifferentStructure testLocal(44);
            IntAdapter local( testLocal );
            std::cout << local.getValue()<<std::endl;
        }
    };

    template <typename T > struct StructWrapper:public ob_traits< T >
    {
        StructWrapper(){};
    /*main.cpp:60: error: 'IntAdapter' was not declared in this scope
    main.cpp:60: error: expected `;' before 'inner'
    main.cpp:60: error: 'inner' was not declared in this scope
    */
        void dumpOuter(const T& tempParam) { IntAdapter inner(tempParam); inner.dump(); };
    /*
    main.cpp: In member function 'void StructWrapper<T>::dumpOuterFailsAsWell(const T&)':
    main.cpp:66: error: expected `;' before 'inner'
    main.cpp:66: error: 'inner' was not declared in this scope
    */
        void dumpOuterFailsAsWell(const T& tempParam) { ob_traits<T>::IntAdapter inner(tempParam); inner.dump(); };
    };

    int main(int argc, char* argv[])
    {
        GeneralStructure dummyGeneral(22);
        ob_traits<struct GeneralStructure >::IntAdapter test(dummyGeneral);
        DifferentStructure dummyDifferent(33);
        ob_traits<struct DifferentStructure >::IntAdapter test2(dummyDifferent);
        std::cout << "GeneralStructure: "<<test.getValue()<<std::endl;
        std::cout << "DifferentStructure: "<<test2.getValue()<<std::endl;
        ob_traits<struct DifferentStructure > test3;
        test3.dump();
    std::cout << "Test Templated\n";
    return 0;
    }

Решение было найдено путем обновления двух строк: void dumpOuterFailsAsWell (const T & tempParam) {'typename' ob_traits <T> :: IntAdapter inner (tempParam); inner.dump (); }; };

Jon Galloway 06.11.2008 18:04

Аналогичная проблема с более кратким объяснением по адресу: stackoverflow.com/questions/11405/template-problem-with-gcc

Superpolock 06.11.2008 06:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
1 554
3

Ответы 3

StructWrapper наследуется от шаблона первичного класса (т.е. наименее специализированного), который не определяет IntWrapper, поэтому его нельзя использовать в этом классе. Я не уверен, что создание экземпляра StructWrapper с одним из более специализированных типов позволит ему работать, или он не сможет скомпилировать само определение класса.

Сбой компиляции, поскольку IntAdapter отображается только в специализированном шаблоне и поэтому не отображается в точке ссылки.

Непонятно, для чего бы вы его использовали? Пожалуйста, проясните обстоятельства.

Я думал, что это должно сработать, потому что IntAdapter публично наследуется в производном классе. Я не понимаю, почему компиляции StructWrapper терпят неудачу. Я хочу создать адаптер на основе шаблонного параметра и использовать этот адаптер для доступа к компонентам класса. Лучшие предложения?

Jon Galloway 06.11.2008 17:21

dumpOuter не работает, потому что IntAdapter должен быть квалифицирован (как в указанном вопросе). dumpOuterFailsAsWell не работает, потому что GCC выполняет синтаксический анализ этого кода, даже если он не завершен, и поэтому ему необходимо знать, что это тип, который вы имеете в виду:

void dumpOuterWorks(const T& tempParam) 
{ 
   typename ob_traits<T>::IntAdapter inner(tempParam); 
   inner.dump(); 
}

Без typename GCC будет считать, что IntAdapter является идентификатором, и будет ожидать, что вы формируете выражение, а не объявление переменной.

Также обратите внимание, что вам не нужно ставить точку с запятой после тела метода!

Другие вопросы по теме