Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.77/13: Рейтинг темы: голосов - 13, средняя оценка - 4.77
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
1

Ошибка вызова конструктора преобразования с аргументом - переменной в области действия данной переменной

22.03.2019, 11:43. Показов 2644. Ответов 93
Метки нет (Все метки)

Всем доброго времени суток.
Увидел на англоязычном сайте школярский вопросик, который может звучать так: "Вывести числа от 1 до 10 и их квадраты на экран". Было пару минут и я написал:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//task
//print seq 1...10 vs their squires
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
 
struct Seq_squer_logger
{
    static string logg;
 
    Seq_squer_logger(int dec, int radix=10)
    {
        const   int size=16;
        char    buff[size],
                buf_sqr[size];
 
        _itoa_s(dec, buff, size, radix);
        _itoa_s(dec*dec, buf_sqr, size, radix);
 
        logg+=buff;
        logg+=" ";
        logg+=buf_sqr;
        logg+="\n";
    }
 
};
string
Seq_squer_logger::logg;
 
int main(int argc, char* argv[])
{
for(int i=1; i!=11; ++i)
Seq_squer_logger(i);//drag coment from lower string to hide that
//Seq_squer_logger slogObj(i);//and creating named object all works right
cout<<Seq_squer_logger::logg;
cout<<endl;
cin.get();
return 0;
}
Оно не скомпилировалось в 2008-й и я подумав, - старый компилятор, попробовал в MinGW. Тоже не компилируется с сообщением:
C:\...\ConsoleTest\main.cpp:2002: ошибка: redefinition of 'i' with a different type: 'Seq_squer_logger' vs 'int'
При чём, если перетащить коммент снизу вверх, то создание именованного объекта компилятор парсит нормально. Если до цикла вызвать:
C++
1
Seq_squer_logger slogObj(123);
Тут, (как и сдеовало ожидать) всё хорошо.
Почему компилятор не желает запускать конструктор для создания временного объекта в данном случае?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.03.2019, 11:43
Ответы с готовыми решениями:

Области действия переменной
void f() { ... // 1 { ... // 2 int i; for(i=0; i&lt;10; ++i) { ......

a,b и c.Присвоить максимальное из них переменной a,минимальное-переменной c,среднее переменной b
даны произвольные числа a,b и c.Присвоить максимальное из них переменной a,минимальное-переменной...

Присвоение конструктора переменной
using System; namespace Test1 { class Program { public static void Main(string args)...

Вывод значения переменной, имя которой задаётся аргументом пакетного файла, без использования команды SET
Есть bat файл для которого в качестве параметра указывается переменная например windir на что...

93
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 12:31 2
Цитата Сообщение от IGPIGP Посмотреть сообщение
C++
1
Seq_squer_logger(i);
C++
1
Seq_squer_logger{i};
А если так?)
Цитата Сообщение от IGPIGP Посмотреть сообщение
C++
1
_itoa_s
А это разве не студийные варианты?

Добавлено через 3 минуты
Цитата Сообщение от Azazel-San Посмотреть сообщение
А если так?)
C++
1
(Seq_squer_logger(i));
Или так.

У меня шланг выдал проблему о unnecessary parentheses in declaration of 'i' [-Wparentheses]

Добавлено через 3 минуты
Цитата Сообщение от Azazel-San Посмотреть сообщение
C++
1
(Seq_squer_logger(i));
Здесь дополнительные дужчки они же parentheses, делают выражение как lvalue.

Добавлено через 23 минуты
Цитата Сообщение от Azazel-San Посмотреть сообщение
делают выражение как lvalue.
Хотя может не в этом случае? Какой результат работы конструктора? prvalue?
Даже если так, это ничего не меняет. Похоже все проще.
Компилятор просто считал что здесь идет объявление переменной как
C++
1
2
3
for(int i = 1; i != 11; ++i)
    Seq_squer_logger i; // т.е. он не видел (), а перед этим уже есть i, объявленная как целое, отсюда и редефинишн
    // а поскольку дефолтного конструктора не было он пытался подставить в другие, но безуспешно (в т.ч. неявные)
.
Но почему он так делал не ясно
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 13:42  [ТС] 3
Цитата Сообщение от Azazel-San Посмотреть сообщение
Но почему он так делал не ясно
Azazel-San, это нормальный глюк (имхо). И мало ли глюков? Нам не быть в печали из-за этого. Просто, предупреждение Мэйерса о том что нужно быть внимательными с "функциональными", в части инициализации, объявлениями выглядит ещё выпуклее. Мне интересно другое. Какова вероятность одного и того же бага на компиляторах разных фирм?. Все мы знаем порядочность майкрософт, в части "заимствований". Претензии злопыхателей беспочвенны, обычно. Если уж не нарочно и это доказано, - они платят. Свободное сообщество вряд ли пошло бы на плагиат у MS. Последние могут откусить руку и воткнуть её не туда где она была изначально.
Что же тут происходит?
Подождём разъяснений от гуру.

Добавлено через 9 минут
Цитата Сообщение от Azazel-San Посмотреть сообщение
Или так.
MinGW со скобками ест нормально.
Но непонятно всё едино.
0
884 / 340 / 78
Регистрация: 17.05.2015
Сообщений: 1,095
22.03.2019, 14:44 4
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но непонятно
Конструкция вида:
C++
1
int(i);
Это тоже самое что:
C++
1
int i;

Можно даже с инициализацией писать:

C++
1
2
int(i) = 10;
std::cout << i;

По аналогии в вашем случае:

C++
1
2
for(int i=1; i!=11; ++i)
        Seq_squer_logger(i);
Интерпретируется как:

C++
1
2
for(int i=1; i!=11; ++i)
        Seq_squer_logger i;
То есть - попытка создать объект класса Seq_squer_logger по имени i
Но в зоне видимости уже есть объект с таким именем: int i

О чем и пытается сообщить вам компилятор:
Код
source_file.cpp:19:26: error: redefinition of 'i' with a different type: 'Seq_squer_logger' vs 'int'
        Seq_squer_logger(i);
                         ^
Ошибка: попытка переопределить переменную "i" как объект другого типа данных: 'Seq_squer_logger' vs 'int'
1
15135 / 8129 / 1965
Регистрация: 30.01.2014
Сообщений: 13,819
22.03.2019, 15:04 5
IGPIGP, Если говорить коротко - в С++ есть правило, грубо сформулировать его можно так:
Если нечто может считаться допустимым объявлением, то оно является таковым
Некоторый разбор есть тут: https://en.wikipedia.org/wiki/Most_vexing_parse
Ну и ссылки в конце страницы, в т.ч. на стандарт.
0
Модератор
Эксперт С++
11130 / 9168 / 5506
Регистрация: 18.12.2011
Сообщений: 24,482
22.03.2019, 16:49 6
Думаю, дабы такие проблемы не возникали стоит писать более осмысленные выражения:
C++
1
2
3
4
5
6
    for (int i = 1; i != 11; ++i)
    {
        Seq_squer_logger::Seq_squer_logger(i);
        cout << Seq_squer_logger::logg;
        cout << endl;
    }
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 17:01  [ТС] 7
Цитата Сообщение от zss Посмотреть сообщение
Думаю, дабы такие проблемы не возникали стоит писать более осмысленные выражения:
?? Это о чём??

Не по теме:

zss я попросил исправить слово "согдания" на "создания" в заголовке.


zss, у вас где-то компилируется то, что вы предложили? Если да, то осмысленным ответом была бы версия компилятора, У меня ваш совет не помогает ни в 2008 ни в MinGW
C:\....\ConsoleTest\main.cpp:2002: ошибка: redefinition of 'i' with a different type: 'Seq_squer_logger' vs 'int'
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 17:01 8
Цитата Сообщение от IGPIGP Посмотреть сообщение
MinGW со скобками ест нормально.
Но непонятно всё едино.
Вероятно дополнительные скобки таки заставляют делать нормальный синтаксический разбор.
Если доп. скобки говорят что внутри выражение стоит воспринимать как lvalue - вероятно тогда парсер делает адекватный разбор выражение, но это очень не точно, эта штука с дужками которую я описал выше так работает с decltype, а его тут нету, так что никакого lvalue здесь может тоже нету, а скобки - просто подсказка.
1
Модератор
Эксперт С++
11130 / 9168 / 5506
Регистрация: 18.12.2011
Сообщений: 24,482
22.03.2019, 17:04 9
Visual Studio 2017
C++
1
Seq_squer_logger::Seq_squer_logger(i);
Вот так компилируется
И по моему обязано компилироваться, т.к. это явное указание на вызов конструктора из класса Seq_squer_logger
1
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 17:08 10
Цитата Сообщение от zss Посмотреть сообщение
Вот так компилируется
Это не должно было помочь.
Шланг все еще выдает ошибку.
1
Модератор
Эксперт С++
11130 / 9168 / 5506
Регистрация: 18.12.2011
Сообщений: 24,482
22.03.2019, 17:10 11
Цитата Сообщение от Azazel-San Посмотреть сообщение
Шланг все еще выдает ошибку.
А попробуйте так:
C++
1
Seq_squer_logger  ss=Seq_squer_logger(i);
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 17:11 12
Вот так точно работает:
Цитата Сообщение от Azazel-San Посмотреть сообщение
C++
1
2
(Seq_squer_logger(i)); // так
Seq_squer_logger{i}; // или так с С++11
Добавлено через 58 секунд
Цитата Сообщение от zss Посмотреть сообщение
А попробуйте так:
Так уже должно сработать, но это не интересно, смотрите мой пост, он первый
Ошибка вызова конструктора преобразования с аргументом - переменной в области действия данной переменной
Ну и последствующие посты, от гуру в т.ч. это - https://en.wikipedia.org/wiki/Most_vexing_parse
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 17:16  [ТС] 13
eva2326, вы пишете именно то, что пишут компиляторы. И похоже что так оно и есть.
Однако, вызов
C++
1
2
int a(3);
Seq_squer_logger((int)a);
работает нормально, то есть получается, в парсерах обоих компиляторов, что одинаковые глюки.
Цитата Сообщение от DrOffset Посмотреть сообщение
Если говорить коротко
DrOffset, я не вижу что в вызове конструктора преобразования недопустимого. Компилятор, действительно, путает его с объявлением и это странно. Более того, найти описание такого поведения (помню один случай у Мэйерса, кажется) очень сложно. Но по логике это ведь глюк?
Если вы покажете, что может рухнуть от попытки научить компилятор спокойно делать такой вызов, я сдаюсь.

Добавлено через 52 секунды
Цитата Сообщение от Azazel-San Посмотреть сообщение
Так уже должно сработать
Но не работает.

Добавлено через 2 минуты
Цитата Сообщение от zss Посмотреть сообщение
Visual Studio 2017
Это доказывает, что у других компиляторов это глюк. Но и без фигурных скобок, следующий оператор - тела цикла. Поэтому глюк есть и у 2017, но менее выраженный.
0
884 / 340 / 78
Регистрация: 17.05.2015
Сообщений: 1,095
22.03.2019, 17:17 14
Цитата Сообщение от zss Посмотреть сообщение
Seq_squer_logger *ss=Seq_squer_logger(i);
Жессть)))

Цитата Сообщение от zss Посмотреть сообщение
И по моему обязано компилироваться, т.к. это явное указание на вызов конструктора из класса Seq_squer_logger

Код
source_file.cpp:12:41: error: cannot call constructor ‘Seq_squer_logger::Seq_squer_logger’ directly [-fpermissive]
     Seq_squer_logger::Seq_squer_logger(i);
                                         ^
source_file.cpp:12:41: note: for a function-style cast, remove the redundant ‘::Seq_squer_logger’
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 17:20  [ТС] 15
Цитата Сообщение от Azazel-San Посмотреть сообщение
Шланг все еще выдает ошибку
Не ужели все скомуниздили "творчески переосмыслили" какой-то один общий исходник для парсера?
0
884 / 340 / 78
Регистрация: 17.05.2015
Сообщений: 1,095
22.03.2019, 17:22 16
Цитата Сообщение от IGPIGP Посмотреть сообщение
Seq_squer_logger((int)a);
Вы никаких различий не замечаете?
Цитата Сообщение от IGPIGP Посмотреть сообщение
Seq_squer_logger(i);
Здесь явный вызов конструктора: Seq_squer_logger((int)a);
Потому что выражение (int)a никак не может быть именем переменной.
А значит вся запись: Seq_squer_logger((int)a); никак не может быть объявлением переменной.
А значит она может быть только и только вызовом функции
(в данном случае - конструктором)
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 17:28 17
Цитата Сообщение от IGPIGP Посмотреть сообщение
Но не работает.
А должен бы работать, тут
C++
1
Seq_squer_logger  ss=Seq_squer_logger(i);
тоже что и
C++
1
Seq_squer_logger  ss(i);
.
Ну, почти тоже, копирование упустим)
Здесь должен быть явный вызов контруктора и неоднозначности быть не может.
У меня msvc v19.0 билдит окей.
Цитата Сообщение от IGPIGP Посмотреть сообщение
C++
1
Seq_squer_logger((int)a);
Здесь тоже самое, не может быть такое выражение Seq_squer_logger (int)a; <- здесь то и заставляем не убирать внешние скобки.
Но и так работает
C++
1
(Seq_squer_logger(a));
<- тут уже не совсем уверен почему (возможно по тем причинам что я писал).
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 17:28  [ТС] 18
Цитата Сообщение от eva2326 Посмотреть сообщение
Вы никаких различий не замечаете?
Замечаю. eva2326, вы читаете всё кроме того, что цитируете? Я понял о чём вы написали и согласен с тем, что так оно и есть. Я не согласен с тем что что правильное поведение. Вон zss, пишет, что с явным указанием скоупа парой (совершенно лишних с точки зрения синтаксиса) фигурных скобок 2017 это есть без проблем. Это значит проблема не с записью, а с тем, что кто-то не умеет её распарсить?
0
Mental handicap
1245 / 623 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
22.03.2019, 17:30 19
Цитата Сообщение от IGPIGP Посмотреть сообщение
Не ужели все скомуниздили "творчески переосмыслили" какой-то один общий исходник для парсера?
У вас студия 2008 года, как знать что там под капотом..
0
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
22.03.2019, 17:38  [ТС] 20
Цитата Сообщение от eva2326 Посмотреть сообщение
А значит вся запись: Seq_squer_logger((int)a); никак не может быть объявлением переменной.
eva2326, я убеждён что это глюк. Компиляторы не должны толковать неправильно всё что можно было бы толковать неправильно, даже с ошибками такого толкования.
eva2326, если есть и (объявлен и определён) конструктор:
C++
1
SomeClass(int)
никогда не значит что имеет смысл запись:
C++
1
int(SomeClasst)
и было бы весело, если бы имела.

Добавлено через 3 минуты
Цитата Сообщение от Azazel-San Посмотреть сообщение
У вас студия 2008 года, как знать что там под капотом..
И MinGW свежий. Под капотом та объектные файлы немалого объёма. Однако поведение очень уж похожее у разных компиляторов. У меня не супер опыт по написанию парсеров, но кое-что есть. Имхо, случайными такие вещи могут быть, но вероятность очень низка.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.03.2019, 17:38

Присвоить значение наименьшего элемента массива переменной М1, номер строки, где находится этот элемент, - переменной Т, номер столбца - переменной С
Массив С действительных чисел имеет 5 строк и 11 столбцов. Присвоить значение наименьшего элемента...

Как присвоить значение переменной в строке вызова скрипта?
Пусть в скрипте z2-5.php переменная $lang может принимать значения &quot;ru&quot;, &quot;en&quot;, &quot;fr&quot; или &quot;de&quot;....

Доступ к переменной через конструктор при перегрузке конструктора
Приветствую ребята. Изучаю Java. Наткнулся на такую штуку. public class test { public...

Действия в переменной
Здравствуйте, форумчане, есть очень странный вопрос. Можно ли проводить сложные операции внутри...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.