Не удалось сделать кросс-компиляцию этого кода между MSVC 2015 и GCC 7.3 - PullRequest
0 голосов
/ 30 января 2019

Когда я писал код для своего проекта, я обнаружил очень странную ситуацию, в которой мой C ++ 11 код не мог быть кросс-скомпилирован между GCC 7.3 и MSVC2015 .Дело в основном в следующем:

// .H file

template <typename X>
struct Outer {
    X x = {};

    template <typename Y>
    struct Inner {
        Y y = {};
        Inner& operator++();
    };
};

// .INL file

template <typename X>
template <typename Y>
inline Outer<X>::Inner<Y>&
    Outer<X>::Inner<Y>::operator++()
{
    ++y;
    return *this;
}

// .CPP file

#include <iostream>

int main()
{
    Outer<int>::Inner<int> a;
    ++a;
    std::cout << a.y << std::endl;

    return 0;
}

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

warning C4346: 'Inner': dependent name is not a type note: prefix with
'typename' to indicate a type error C2061: syntax error: identifier
'Inner' error C2143: syntax error: missing ';' before '{' error C2447:
'{': missing function header (old-style formal list?)

Как предполагает сам компилятор MSVC, написание ключевого слова typename для возвращаемого типа решит проблему:

template <typename X>
template <typename Y>
inline typename Outer<X>::Inner<Y>&
Outer<X>::Inner<Y>::operator++()
{
    ++y;
    return *this;
} 

Но теперь, что удивительно, GCC больше не будет компилировать, и его ошибка:

error: non-template 'Inner' used as template
     inline typename Outer<X>::Inner<Y>&
                               ^~~~~ note: use 'Outer<X>::template Inner' to indicate that it is a template error: expected
unqualified-id at end of input

Опять же, как предложил сам компилятор, я попытался добавить ключевое слово template к возвращаемому типу,и это исправит проблему для GCC:

template <typename X>
template <typename Y>
inline typename Outer<X>::template Inner<Y>&
Outer<X>::Inner<Y>::operator++()
{
    ++y;
    return *this;
}

Но теперь это исправление снова сломает сборку MSVC, и ошибка компилятора:

error C2244: 'Outer<X>::Inner<Y>::operator ++': unable to match
function definition to an existing declaration note: see declaration
of 'Outer<X>::Inner<Y>::operator ++' note: definition note:
'Outer<X>::Inner<Y> &Outer<X>::Inner<Y>::operator ++(void)' note:
existing declarations note: 'Outer<X>::Inner<Y>
&Outer<X>::Inner<Y>::operator ++(void)'

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

На данный момент, не зная ничего лучшегоВ качестве решения я решил просто определить функцию внутри области действия класса Inner в файле .H, и это будет работать как для GCC, так и для MSVC.Но некоторые вопросы все еще остаются: кто прав?GCC или MSVC?Или это стандарт C ++, который в этом случае слишком неоднозначен?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Кажется, это работает для всех протестированных мной компиляторов:

template <typename X>
template <typename Y>
inline auto Outer<X>::Inner<Y>::operator++() 
    -> Inner<Y> &
{
    ++y;
    return *this;
}
0 голосов
/ 30 января 2019

VS 2017 ( 15.9 обновление ) создает этот код просто отлично.Обновление до последней версии, более совместимой с C ++ 11 / C ++ 14, чем VS 2015 Update 3.

cl /permissive- /W4 /EHsc t.cpp

Проверьте Community Edition , чтобы узнать,лицензия соответствует вашим требованиям.

...