Почему я не могу получить доступ к методам предков из шаблонных функций-предшественников в gcc? - PullRequest
0 голосов
/ 14 июля 2011

У меня проблема с шаблонами функций-членов класса.Похоже, что gcc пытается проанализировать код семантически слишком рано, без явной реализации шаблона.

Пусть код говорит

А-ч (базовый класс):

#ifndef __A_H__
#define __A_H__
class A {
public:
    A* ptr;

    template<class T>
    void method() {
        ((B*) ptr)->invoke();
    }
};
#endif 

Bh (предок):

#ifndef __B_H__
#define __B_H__
#include<cstdio>
class B : public A {
        public:
        void invoke() {
                printf("Method invoked\n");
        }
};
#endif 

main.cpp:

#include"A.h"
#include"B.h"

int main() {
        A a;
        a.ptr = new B();
        a.method<int>();
}

Этот код компилируется и работает нормально в Visual Studio 2010 и не компилируется со следующей ошибкой в ​​gcc 4.5:

В файле из main.cpp: 1: 0: Ah: В функции-члене 'void A :: method ()': Ah: 10: 5: ошибка: 'B' не было объявленов этой области Ah: 10: 7: ошибка: ожидаемое первичное выражение перед маркером ')' Ah: 10: 9: ошибка: ожидаемое ')' перед 'ptr'

Почему gcc пытаетсяскомпилировать код A :: method <> () перед запуском какой-либо реализации?Какой компилятор ведет себя в соответствии со стандартом?

ОБНОВЛЕНИЕ: Теперь я знаю, что Visual Studio ведет себя некорректно.B не зависит от параметров шаблона, поэтому он не просматривается при создании экземпляра, но при разборе Ah ( релевантный gcc doc )

Ответы [ 2 ]

3 голосов
/ 14 июля 2011

Код неправильно компилируется в Visual Studio из-за способа обработки шаблонов (в основном они игнорируются, пока не будут созданы экземпляры). В вашем коде идентификатор B не зависит от аргументов шаблона (T) и поэтому должен быть доступен в контексте, где определен шаблон.

Поскольку B наследует от A, это делает все еще более сложным, поскольку в коде есть циклическая зависимость. Я бы пересмотрел дизайн, и если вы считаете, что так и должно быть, я бы объединил два заголовочных файла в один:

// merged.h
struct A {
   A* ptr;
   template<class T>
   void method();
};

struct B : public A {
   void invoke() {
      printf("Method invoked\n");
   }
};

template <typename T>
void A::method() {
   ((B*) ptr)->invoke();
}

Тем не менее, мой совет состоял бы в том, чтобы пересмотреть вопрос о том, имеет ли это отношение вообще смысл, поскольку method налагает ограничение на то, что ptr должно быть B, и это звонит в некоторые колокола кода запах.

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

ne555 с форума cplusplus.com дал мне несколько удачных решений:

new Ah:

#ifndef __A_H__
#define __A_H__

class A {
    public:

    A* ptr;

    template<class T>
    void method();
};

#include"B.h"

template<class T>
void A::method(){
    ((B*)ptr)->invoke();
}

#endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...