Шаблонная функция C ++ и прямые объявления - PullRequest
1 голос
/ 03 сентября 2010

Я работаю над кодом, который компилирует и связывает (и даже выпускает коммерческие продукты) для Windows, используя MSVC. Это не компилируется с GCC, но я получаю следующие ошибки:

.../CBaseValue.h: In member function 'bool CBaseValue::InstanceOf()':
.../CBaseValue.h:90:18: error: invalid use of incomplete type 'struct CValueType'
.../CBaseValue.h:11:7: error: forward declaration of 'struct CValueType'

CBaseValue.h

class CValueType;

class CBaseValue {
public:

...

    template <typename _Type>
    bool InstanceOf() {
        CValueType* pType = GetType();
        if(pType == NULL) {
            return false;
        }
        else {
            return pType->IsDerivedFrom<_Type>();
        }
    }

...

}

CValueType.h

class CValueType : public CBaseValue  {
public:

...

    template <typename _Type>
    bool IsDerivedFrom() {
        return IsDerivedFrom(_Type::TYPEDATA);
    }

...

}

Я понимаю, почему это проблема. Базовый класс (CBaseValue) имеет шаблонную функцию, которая использует производный класс (в данном случае CValueType).

Похоже, MSVC не совсем подчиняется спецификации C ++, и я только что ее укусил. Но поведение MSVC использования прямого объявления до тех пор, пока код, вызывающий шаблонную функцию, не будет фактически скомпилирован, также более желательно прямо сейчас. Кто-нибудь знает обходной путь, где я могу заставить этот код работать с GCC без необходимости переписывать много базового кода?

Из моего собственного исследования похоже, что передача '-fno-implicit-templates' в g ++ могла бы помочь, но тогда мне нужно было бы явно определить вызываемые типы шаблонов. Их много, поэтому, если я смогу избежать этого, я бы предпочел это. Если общее мнение таково, что это мой лучший вариант ... пусть будет так!

И если кому-то интересно, я переношу код на Mac, поэтому мы сейчас используем GCC.

Ответы [ 2 ]

4 голосов
/ 03 сентября 2010

Стандарт не соответствует требованиям, но диагностика не требуется.MSVC прекрасно не диагностирует этот частный случай (даже когда происходит инстанцирование!).

Более конкретно, (C ++ 03) Стандартные правила в 14.6 / 7

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

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

template<typename T, typename> // just ignore second param!
struct make_dependent { typedef T type; };

template <typename Type> // eww, don't use "_Type" in user code
bool InstanceOf() {
    typename make_dependent<CValueType, Type>::type* pType = GetType();
    // ...
        return pType->template IsDerivedFrom<Type>();
    // ...
}
0 голосов
/ 03 сентября 2010

Кажется, что функция CBaseValue::InstanceOf() бесполезна для всех, кроме CValueType.h.

Так что дождитесь предоставления определения, пока все необходимые типы не станут доступны.(РЕДАКТИРОВАТЬ: Это именно то, что предложено в комментарии Чарльза Бейли, который он разместил, когда я печатал - я думаю, мы думаем одинаково.)

class CValueType : public CBaseValue  {
public:

...

    template <typename T>
    bool IsDerivedFrom() {
        return IsDerivedFrom(T::TYPEDATA);
    }

...

}


template <typename T>
inline bool CBaseValue::InstanceOf() {
        CValueType* pType = GetType();
        if(pType == NULL) {
            return false;
        }
        else {
            return pType->IsDerivedFrom<T>();
        }
    }

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

...