Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.89/9: Рейтинг темы: голосов - 9, средняя оценка - 4.89
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
1

Непонятки с конвертацией типов

01.07.2012, 20:27. Показов 1770. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Краткое описание примера. Определен класс Foo, единственное поле которого -- константная ссылка (const std::string &).
В классе определены лишь конструктор с сигнатурой Foo(const std::string &) и оператор конвертации обратно в константную ссылку на строку.
C++
1
2
3
4
5
6
7
8
class Foo {
  public:
    typedef const std::string & ValT;
    Foo(const std::string & _str) : str(_str) {}
    operator ValT() { return str; }
  private:
    ValT str;
};
  1. Строим объект foo класса Foo, конвертируем его в (const std::string &) и распечатываем:
    C++
    1
    2
    3
    
    std::string str("abcdef");
    Foo foo(str);
    std::cout << (const std::string &) foo << std::endl;
    Посмотреть результат компиляции
    Все отлично компилируется и работает как задумано.
  2. Теперь же попробуем перед печатью конвертнуть объект foo в (std::string &) (т.е. без const):
    C++
    1
    
    std::cout << (std::string &) foo << std::endl;
    Посмотреть результат компиляции
    Компилятор все прожевывает, компилирует, но при попытке исполнить получившийся бинарник выводится куча мусора вместо ожидаемой строки.
    Output limit exceeded. Application output is limited to 10240 symbols

Теперь вопросы:
  1. Почему вообще во втором случае компиляция оказывается успешной? Как компилятор умудряется конвертировать объект типа Foo в (std::string&), если для этого типа определена только конвертация в тип (const std::string &)?
  2. И как объяснить результат выполнения полученного бинарника? Т.е. даже если предположить, что компилятор тупо начхал на спецификатор const и просто использовал const std::string & как std::string &, то, казалось бы, все равно должна бы была вывестись та же самая строка "abcdef". Но на деле все совсем не так.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.07.2012, 20:27
Ответы с готовыми решениями:

Проблема с конвертацией.
У меня такая проблема. В StringGrid есть список дат в виде дд.мм.гггг. Делю на лексемы(день,...

Ошибка с конвертацией?
import java.util.Scanner; public class Program { public static void main(String args) { ...

Проблемы с конвертацией скриптов
Всем привет. Возникла необходимость переделать ВБ скрипт на джавовский. Переделал. Ругаться не...

Проблема с конвертацией в Excel
Нужна помощь чайнику, Отчет, созданный в 1С бухгалтерии конвертирован в Excel, но в Excel не...

13
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
01.07.2012, 20:48 2
Цитата Сообщение от yekka Посмотреть сообщение
Почему вообще во втором случае компиляция оказывается успешной? Как компилятор умудряется конвертировать объект типа Foo в (std::string&), если для этого типа определена только конвертация в тип (const std::string &)?
Ну ведь
Цитата Сообщение от yekka Посмотреть сообщение
C++
1
(std::string &) foo
- это явное приведение, ответственнонсть за последствия уже не на компиляторе. С неявным так не выйдет:
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
#include <iostream>
#include <string>
 
 
struct foo {
   
   foo(std::string const& string) : string(string) {}
   
   operator std::string const&() const {
      return string;
   }
 
private:
   std::string const& string;
};
 
 
int main() {
    std::string string("something");
    foo object(string);
    
    std::string const& constRef = object;
    std::cout << constRef << std::endl;
    
    // should fail
    // std::string & mutableRef = object;
    // std::cout << mutableRef << std::endl;
}
http://liveworkspace.org/code/... 8109e10391
1
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
01.07.2012, 21:01  [ТС] 3
а я почему-то был уверен, что явное приведение типов ограничивается только возможностями static_cast и reinterpret_cast, которые константность менять не могут. но сейчас проверил, оказалось, что я ошибался.
0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
01.07.2012, 21:13 4
Цитата Сообщение от yekka Посмотреть сообщение
я почему-то был уверен, что явное приведение типов ограничивается только возможностями static_cast и reinterpret_cast
По моему лучше вообще не пользоваться C-style cast в C++, как минимум, так константность можно снять только с помощью const_cast .
0
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
01.07.2012, 21:22  [ТС] 5
походу возник еще один вопрос
допустим, мы хотим писать
C++
1
std::cout << foo << std::endl
то получаем ошибку, суть которой в том, что оператор << определен для целых чисел, для чисел с плавающей точкой, для указателей и для манипуляторов и ни в один из этих типов Foo конвертировать нельзя.
Результат компиляции
Ну и если добавить в класс Foo operator float(), то все действительно без проблем компилируется:
http://liveworkspace.org/code/... 3fbd4dd823

Но вот непонятно, почему компилятору не видна версия operator<< для строк. Ведь такая версия есть.
Можно было бы предположить, что оператор << для строк объявлен как шаблонная ф-ция, не имеющая общего определения, но имеющая только специализации для конкретных типов, но тогда бы ошибка была бы другой, что-то вроде undefined reference to...
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.07.2012, 16:51 6
yekka, Видна.

In file included from include/c++/4.7.1/string:54:0,
from include/c++/4.7.1/bits/locale_classes.h:42,
from include/c++/4.7.1/bits/ios_base.h:43,
from include/c++/4.7.1/ios:43,
from include/c++/4.7.1/ostream:40,
from include/c++/4.7.1/iostream:40,
from source.cpp:1:
include/c++/4.7.1/bits/basic_string.h:2750:5: note: template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::basic_string<_CharT, _Traits, _Alloc>&)
include/c++/4.7.1/bits/basic_string.h:2750:5: note: template argument deduction/substitution failed:
source.cpp:17:18: note: 'Foo' is not derived from 'const std::basic_string<_CharT, _Traits, _Alloc>'
Кстати при явном преобразовании все ок. http://liveworkspace.org/code/... ba7c310315

Добавлено через 33 минуты
http://liveworkspace.org/code/... ec99f77a97

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

Добавлено через 2 часа 14 минут
Расклад такой.
http://stackoverflow.com/quest... -operators

Добавлено через 11 минут
Итого для работы того кода достаточно сделать так.

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
#include <iostream>
#include <string>
 
std::ostream& operator << (std::ostream& os, const std::basic_string<char>& obj)
{
   return std::operator << (os, obj);
}
 
class Test
{
public:
   explicit Test(const std::string& s_):s(s_)
   {
   }
   operator std::string() const { return s; }
private:
   std::string s;
};
 
int main()
{
   Test t("Hello");
   std::cout << t << std::endl;
}
http://liveworkspace.org/code/... 7c796294de
2
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
03.07.2012, 18:53  [ТС] 7
когда перекрываются перегруженные функции, шаблонные функции и их специализации, получается крайне неочевидные результаты

статья в тему -- http://www.gotw.ca/publications/mill17.htm
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
03.07.2012, 19:20 8
yekka, В представленном выше коде нет никаких специализаций и неочевидного ничего здесь нет, ибо в варианты попадают все операторы <<, объявленные в хедер-файлах в области видимости пространства имен std + глобальная область видимость, в std есть оператор вывода для string, но он шаблонный, в глобальной же области видимости оператор не шаблонный, следовательно он и выбирается.
0
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
03.07.2012, 22:45  [ТС] 9
Сегодня 16:51
Цитата Сообщение от ForEveR Посмотреть сообщение
Вообщем довольно странный расклад. Он не может конвертнуть к шаблонному типу, почитаю стандарт поищу, в разделе 12.2.3 про это ничего нет. Может и gcc косячит.
Сегодня 19:20
Цитата Сообщение от ForEveR Посмотреть сообщение
неочевидного ничего здесь нет



Тем не менее, не понятно, почему в случае
http://liveworkspace.org/code/... ee6adf3e81
бьется память, а, казалось бы, аналогичный вариант с const_cast и static_cast
http://liveworkspace.org/code/... 13a51ba7a3
исправно работает?

Как выяснилось, первом случае генерится код с точностью до хеша совпадающий с вот этим вариантом, использующим const_cast и reinterpret_cast:
http://liveworkspace.org/code/... d42d069f0d
Остается только разобраться, почему здесь компилятором используется reinterpret_cast, а не static_cast
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
04.07.2012, 00:12 10
yekka, Я про последний свой код говорил)
Что делает приведение типов в стиле С: пытается использовать static_cast, если не получается, использует reinterpret_cast. Далее, если нужно, использует const_cast .
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
04.07.2012, 00:16 11
Цитата Сообщение от yekka Посмотреть сообщение
а, казалось бы, аналогичный вариант с const_cast и static_cast
http://liveworkspace.org/code/... 13a51ba7a3
исправно работает?
что-то таки const_cast делает, непросто ж так его ввели

Не по теме:

ещё один довод в пользу кастов

0
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
04.07.2012, 07:42  [ТС] 12
Цитата Сообщение от ForEveR Посмотреть сообщение
Что делает приведение типов в стиле С: пытается использовать static_cast, если не получается, использует reinterpret_cast. Далее, если нужно, использует const_cast .
ну так об том и речь. в данном случае вполне достаточно static_cast'а, но компилятор почему-то использует reinterpret_cast
0
Эксперт С++
5055 / 3115 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
04.07.2012, 12:40 13
yekka, потому что не надо, как уже говорили, использовать каст в С-стиле.
0
387 / 151 / 16
Регистрация: 12.05.2011
Сообщений: 450
05.07.2012, 20:55  [ТС] 14
Цитата Сообщение от silent_1991 Посмотреть сообщение
yekka, потому что не надо, как уже говорили, использовать каст в С-стиле.

Не по теме:

ну если нечего сказать по делу, то зачем же флудить-то?



что-то не могу понять.
с одной стороны, стандарт явно утверждает, что при c-style приведении типов комбинация const_cast + reinterpret_cast должна использоваться только в том случае, когда const_cast + static_cast не справляются.
с другой стороны, и gcc, и clang в данном случае (http://liveworkspace.org/code/... ee6adf3e81) используют reinterpret_cast
0
05.07.2012, 20:55
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.07.2012, 20:55
Помогаю со студенческими работами здесь

Проблемы с конвертацией из 97 в 2000 access ...
Привет All! Проблема такова: Имеем NT 4.0 Eng SP6a + IIS 5.0 ... На серванте лежит база 2000...

Проблема с конвертацией textbox на 20-й строчке
namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1()...

Проблемы с конвертацией Mime в Richtext
И вот такая теперь у меня проблема. Пришло письмо в лотус из OutLook. Оно в MIME формате. Вообще...

Затруднения с конвертацией html в Wordpress
Крч я интегрировал главную стр. не разбивая ее на headphp footer и.т.д, но есть еще внутренние...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru