GCC два необычных сообщения об ошибках - PullRequest
3 голосов
/ 14 марта 2011

Сегодня я столкнулся с двумя сообщениями об ошибках, которых я никогда не видел прежде Это совершенно ново для меня.

Вот код:

template<typename T>
struct adder { adder(const T &item) { } };

template<typename T>
void initializer(const T &item) {  adder<T>(item); }

int main() 
{
   initializer("const string literal");
}

При компиляции GCC выдает следующие ошибки:

prog.cpp: в функции «void initializer (const T &)»:
prog.cpp: 6: ошибка: объявление ‘сумматора элемент’ затеняет параметр
prog.cpp: В функции initial void initializer (const T &) [with T = char [21]] ’:
prog.cpp: 10: создается здесь
prog.cpp: 6: ошибка: объявление «adder item» затеняет параметр
prog.cpp: 6: ошибка: отсутствует функция сопоставления для вызова call adder :: adder () ’
prog.cpp: 3: примечание: кандидаты: adder :: adder (const T &) [с T = char [21]]
prog.cpp: 3: note: adder :: adder (const adder &)


См. Жирный текст. Одна ошибка отображается дважды , это

ошибка: объявление 10 сумматора item ’затеняет параметр
ошибка: объявление ‘adder item ’ затеняет параметр

Что это значит? Почему он показывает дважды с разными аргументами шаблона? Первый с T, второй с char [21]?

EDIT: adder<T>(item) объявляет переменную с именем item ? Но это не то, что я хотел. Я думаю, что он должен создать временный объект, передавая item в качестве аргумента конструктору.

Я хотел бы знать раздел из Стандарта, который касается этой проблемы!


Другая интересная ошибка:

ошибка: не найдена соответствующая функция для вызова ‘adder :: adder ()’

Что указывает на то, что компилятор ищет конструктор по умолчанию ? Но мне интересно, почему компилятор ищет его, когда фактически мой код не использует его в строке 6 ?


Код в ideone: http://www.ideone.com/jrdLL

Ответы [ 4 ]

4 голосов
/ 14 марта 2011

Что указывает на то, что компилятор ищет конструктор по умолчанию? Но мне интересно, почему компилятор ищет его, когда фактически мой код не использует его в строке 6?

Поскольку компилятор считает, что вы объявляете локальную переменную с именем item.

http://codepad.org/YBPKCvmm

3 голосов
/ 14 марта 2011

В данный момент у меня есть доступ только к черновику C ++ 0x, поэтому я не могу дать вам текущую главу и стих, но я не думаю, что многое изменилось. В 0x это в разделе 6.8 - Разрешение неоднозначности:

В грамматике есть двусмысленность включая выражения-выражения и объявления: выражение-утверждение с явным типом в стиле функции преобразование (5.2.3) в крайнее левое положение подвыражение может быть неразличимым из декларации, где первый Декларатор начинается с (. В тех В случаях, когда заявление является декларацией.

[...]

T(a); // declaration

То есть объявление переменной с именем "a" типа T.

Если бы ваш adder<T>(item) должен был определить временный (неименованный) объект, это был бы оператор выражения, но если что-то можно проанализировать как оператор объявления или оператор выражения, C ++ анализирует его как декларация-заявление.

[...] решение заключается в рассмотрении любого построить, что может быть декларация декларация. (8,2)

Другими словами, это двоюродный брат каждого дорогого старого друга, самого мрачного парса.

Обновление: Я посмотрел на разрешение неоднозначности в C ++ 03, и эти отрывки идентичны.

3 голосов
/ 14 марта 2011

Ключом к пониманию происходящего является осознание того, что: сумматор (предмет);является определением локальной переменной с именем item и имеющим тип adder;круглые скобки излишни, но вполне допустимы.Если вы хотите вызвать конструктор, вам придется устранить неоднозначность, записав его некоторым образом, который не может быть интерпретирован как определение данных, скажем: adder ((item));(Я не уверен, что это может быть использовано. Он создает временный объект сумматора, а затем уничтожает его в конце выражения.)

Фактические сообщения об ошибках должны быть удалены (er) после утвержденияпонимается как объявление данных: параметры функции обрабатываются так, как если бы они были определены в блоке верхнего уровня функции, поэтому adder (item) является дублирующим (и противоречивым) определением, а adder не имеет конструктора по умолчанию, поэтомувы не можете определить его экземпляр без предоставления аргументов.

1 голос
/ 14 марта 2011

«Затенение» означает, что два объекта имеют одно и то же имя, которое язык разрешает на данный момент, но может не быть предназначенным.

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