Почему компилятор пытается создать экземпляр шаблона, который я на самом деле нигде не создаю? - PullRequest
15 голосов
/ 07 июня 2011

Обновление ниже .
Ниже приведен весь код, который есть в моем файле main.cpp:

template<class T>
struct other_traits;

template<class T>
struct some_traits{
    typedef decltype(&T::operator()) Fty;
    typedef typename other_traits<Fty>::type type;
};

int main(){
}

Но я получаю следующие ошибки в Visual Studio 2010, пока g ++ прекрасно компилируется :

src \ main.cpp (9): ошибка C2146: синтаксическая ошибка: отсутствует ';'перед идентификатором 'type'
--src \ main.cpp (10): см. ссылку на экземпляр шаблона класса 'some_traits<T>', который компилируется
src \ main.cpp (9): ошибка C2868: 'some_traits<T>::type ': недопустимый синтаксис для объявления об использовании;ожидаемое квалифицированное имя

(мне нравится это последнее, общее вес.)

Могу ли я считать это ошибкой в ​​VC10 или есть какая-то веская причина для раннего создания экземпляра?Или это ошибка с decltype, из-за которой компилятор считает, что Fty не является зависимым именем?


Обновление : я пытался обмануть компилятор, думая, чтоFty является зависимым именем, использующим базовый класс для наследования:

template<class T>
struct other_traits;

template<class R, class C>
struct other_traits<R (C::*)()>{
    typedef R type;
};

template<class Fty>
struct base_traits{
    typedef typename other_traits<Fty>::type type;
};

template<class T>
struct some_traits
    : public base_traits<decltype(&T::operator())>
{};

Но компилятор все еще пытается создать экземпляр / скомпилировать все на месте, выпуская эти ошибки:

src\main.cpp(13): error C2039: 'type' : is not a member of 'other_traits<T>'
          with
          [
              T=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'base_traits<Fty>' being compiled
          with
          [
              Fty=
          ]
          src\main.cpp(19) : see reference to class template instantiation 'some_traits<T>' being compiled
src\main.cpp(13): error C2146: syntax error : missing ';' before identifier 'type'
src\main.cpp(13): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
src\main.cpp(13): error C2602: 'base_traits<Fty>::type' is not a member of a base class of 'base_traits<Fty>'
          with
          [
              Fty=
          ]
          src\main.cpp(13) : see declaration of 'base_traits<Fty>::type'
          with
          [
              Fty=
          ]
src\main.cpp(13): error C2868: 'base_traits<Fty>::type' : illegal syntax for using-declaration; expected qualified-name
          with
          [
              Fty=
          ]

Обратите внимание, что параметры шаблона пусто .Есть идеи?

Ответы [ 4 ]

2 голосов
/ 07 июня 2011

Кажется, это Ошибка (если не указан специальный флаг, как указано ниже). Ниже приводится выдержка из веб-сайта Oracle для шаблонов C ++:

7.2.2

Стандарт ISO C ++ Разрешения разработчики писать шаблоны классов для которого не могут быть все участники законный с данным шаблоном аргумент. Пока незаконно члены не созданы , Программа все еще хорошо сформирована. ISO Стандартная библиотека C ++ использует это техника. Тем не менее Опция -template = wholeclass создает все элементы и, следовательно, нельзя использовать с таким шаблоном классы при создании экземпляра с проблемные аргументы шаблона.

1 голос
/ 08 июня 2011

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

0 голосов
/ 08 июня 2011

Вы делаете одно предположение здесь, это технически неверно.давайте сначала разберемся с этим.

Вы предполагаете, что синтаксическая ошибка означает, что шаблон создан.Это не то, как шаблоны должны быть скомпилированы.Шаблон сначала компилируется перед созданием экземпляра.Это фаза, в которой ищутся независимые имена.Синтаксические ошибки, безусловно, можно найти на этом этапе.Например, все, что обязательно является объявлением независимо от аргументов шаблона, должно заканчиваться ;.

. Теперь правильный вопрос - верен ли компилятор при рассмотрении специализаций other_traits<T>.Конечно, в строке 9 таких специализаций нет, хотя позже могут появиться другие.Но будет ли актуальным моментом для них?Я должен был бы посмотреть это (извините, AFS Away From Standard_traits будет строкой 9, тогда , если нет специализаций, и other_traits<Fty>::type недействительно. Если точка создания экземпляра для other_traits<Fty>::type будет таким же, как точка создания экземпляра для some_traits<T>, т. е. ни одного, тогда other_traits<Fty>::type должно быть принято на этапе 1.

0 голосов
/ 07 июня 2011
template<class T>
struct other_traits; // <-- I don't see a "type" attribute in this struct

template<class T>
struct some_traits{
    typedef decltype(&T::operator()) Fty;
    typedef typename other_traits<Fty>::type type; // <-- Here you are trying to access other_traits<T>::type which doesn't exist
};

int main(){
}
...