Форум программистов, компьютерный форум CyberForum.ru

Приоритет преобразований внутри if - C++

Восстановить пароль Регистрация
 
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
22.07.2013, 11:18     Приоритет преобразований внутри if #1
Всем привет.

Рассмотрим такой код:
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
#include <iostream>
 
class C {
    typedef void (C::*fp)() const;
public:
    operator fp() const 
    { 
        std::cout << "fp conversion\n";
        return 0; 
    }
    operator bool() const 
    { 
        std::cout << "bool conversion\n";
        return false; 
    }
    operator int() const 
    { 
        std::cout << "int conversion\n"; 
        return 0; 
    }
};
 
int main()
{
    C c;
    if( c )  { /* do smth */  }
}
В данном случае вывод будет такой:
bool conversion
Если убрать operator bool, то такой:
int conversion
И если теперь убрать и operator int, то такой:
fp conversion
Отсюда вопрос: какой приоритет вызова преобразований в условной конструкции if, каким пунктом стандарта это регламентируется?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
22.07.2013, 11:22     Приоритет преобразований внутри if #2
Ох, как бы так вспомнить чтобы не соврать...
Для операторов вроде два этапа:сначала пользовательские преобразования, потом стандартные. Т.е. пока есть bool, объект сразу приводится к нему. Если нет bool, но есть int, то сначала выполняется приведение к int, а уже int можно привести к bool.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
22.07.2013, 11:35  [ТС]     Приоритет преобразований внутри if #3
Цитата Сообщение от 0x10 Посмотреть сообщение
Если нет bool, но есть int, то сначала выполняется приведение к int, а уже int можно привести к bool.
Ну, это мы видим из результатов выполнения. Просто хотелось бы не быть голословным. Вот есть пункт стандарта например:
4.12 Boolean conversions
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool.
A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true.
A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
Но про приоритет тут ни слова. Вероятно нужен другой пункт. Но какой?
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
22.07.2013, 12:02     Приоритет преобразований внутри if #4
Последний абзац: http://en.cppreference.com/w/cpp/language/implicit_cast
Где конкретно искать в стандарте - не подскажу.

Добавлено через 2 минуты
Видимо 13.3.3.1 Implicit conversion sequences
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
22.07.2013, 12:05     Приоритет преобразований внутри if #5
Chapter 4 Standard conversions
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
22.07.2013, 18:18  [ТС]     Приоритет преобразований внутри if #6
Цитата Сообщение от 0x10 Посмотреть сообщение
http://en.cppreference.com/w/cpp/language/implicit_cast
Кстати, интересный момент по ссылке.
Implicit conversion sequence consists of the following, in this order:
1) zero or one standard conversion sequence
2) zero or one user-defined conversion
3) zero or one standard conversion sequence
Думал сначала, что опечатка, т.к. пп. 1 и 3 одинаковые. Оказалось, что нет. Например для случая когда отсутствует operator bool получаем: 0 - 1(C->int) - 1(int->bool).

А еще меня смутил пункт:
Qualification conversions
A prvalue of type pointer to member of cv-qualified type T in class X can be converted to prvalue pointer to member of more cv-qualified type T in class X.
Это о каких преобразованиях речь? Если что-то типа этого:
Кликните здесь для просмотра всего текста
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>
 
class C
{
public:
    void f() { std::cout << "f()\n"; }
    void g() const { std::cout << "g()\n"; }
    typedef void (C::*fp)();
};
 
int main() {
    
    C::fp pointer = &C::f;
    
    C c;
    
    (c.*pointer)();
    
    pointer = &C::g; // Не работает
    
    (c.*pointer)();
    
    return 0;
}
, то не работает. https://ideone.com/p0Ym87.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11838 / 6817 / 771
Регистрация: 27.09.2012
Сообщений: 16,911
Записей в блоге: 2
Завершенные тесты: 1
22.07.2013, 18:31     Приоритет преобразований внутри if #7
Я бы еще добавил в класс такой оператор:
C++
1
2
3
4
     operator void*(){
        std::cout << "void* conversion\n"; 
        return 0; 
     }
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
22.07.2013, 18:40  [ТС]     Приоритет преобразований внутри if #8
Croessmah, кстати, не понятно почему в if'е предпочтение отдается operator void*, а не operator bool.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
22.07.2013, 18:42     Приоритет преобразований внутри if #9
Tulosba, по ссылке как раз описано.
Указатель может быть приведен к булу. И это нормально, на этом преобразование заканчивается.
А если есть приведение к булу, то объект далее может быть приведен к инту. Поэтому возможен всякий бред в духе int n = std::cin.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
22.07.2013, 18:52  [ТС]     Приоритет преобразований внутри if #10
Цитата Сообщение от 0x10 Посмотреть сообщение
Указатель может быть приведен к булу. И это нормально, на этом преобразование заканчивается.
Так ведь "родной" тип для условного выражения внутри if'а - bool. Из этого исхожу.
P.S. Кстати, если сделать explicit operator void* (С++11), то вызываться будет уже operator bool.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
22.07.2013, 19:07     Приоритет преобразований внутри if #11
Tulosba, забудем пока про С++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
25
26
27
28
29
30
31
32
33
class A
{
public:
    operator bool() const { return true; }
};
 
class B
{
public:
    operator void*() { return NULL; }
};
 
int main()
{
    A obj;
    // Вызывается сразу пользовательский operator bool
    if (obj) { }
 
    // вызывается operator bool,
    // а затем стандартное преобразование bool -> int
    // Кажется, мы не этого хотели.
    int n = obj;
 
    B obj2;
 
    // Вызывается operator void*, затем стандартное преобразование void* -> bool
    if (obj2) { }
 
    // а вот такой ереси уже сделать нельзя, т.к. указатель неявно не приводится к int.
    //int m = obj2;
 
    return 0;
}
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
23.07.2013, 13:05  [ТС]     Приоритет преобразований внутри if #12
Цитата Сообщение от 0x10 Посмотреть сообщение
// Вызывается operator void*, затем стандартное преобразование void* -> bool
Это потому что других пользовательских преобразований нет.
Предлагаю посмотреть на такой код и поубирать операторы преобразования по очереди:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
 
class B
{
public:
    operator bool() { std::cout << "B::bool\n"; return true; } // 1
    operator void*() { std::cout << "B::void*\n"; return NULL; } // 2
    operator bool() const { std::cout << "B::bool const\n"; return true; } // 3
    operator void*() const { std::cout << "B::void* const\n"; return NULL; } // 4     
};
 
int main()
{
    B obj2;
 
    // Вызывается operator bool, если нет, то operator void*, если нет, то operator bool const, если нет, то operator void* const
    if (obj2) { }
 
    return 0;
}
Собственно, в этом случае как раз видно, что преобразование к bool приоритетнее (при одинаковый cv-квалификаторах), чем преобразование к void*

Добавлено через 15 часов 26 минут
Цитата Сообщение от 0x10 Посмотреть сообщение
Поэтому возможен всякий бред в духе int n = std::cin.
Где возможен?
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
23.07.2013, 13:11     Приоритет преобразований внутри if #13
Цитата Сообщение от Tulosba Посмотреть сообщение
Где возможен?
Был бы возможен, будь у класса оператор приведения к bool.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11838 / 6817 / 771
Регистрация: 27.09.2012
Сообщений: 16,911
Записей в блоге: 2
Завершенные тесты: 1
23.07.2013, 13:23     Приоритет преобразований внутри if #14
Цитата Сообщение от 0x10 Посмотреть сообщение
Был бы возможен, будь у класса оператор приведения к bool.
explicit
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
23.07.2013, 13:31     Приоритет преобразований внутри if #15
Цитата Сообщение от Croessmah Посмотреть сообщение
explicit
Знаю. Чуть выше сказал, что пока забываем про 11 стандарт - по крайней мере, тогда становится понятно зачем писать оператор void*.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.07.2013, 13:47     Приоритет преобразований внутри if
Еще ссылки по теме:

C++ приоритет потоков
C++ Написать программу преобразований массива
C++ Приоритет операторов

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

Или воспользуйтесь поиском по форуму:
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
23.07.2013, 13:47  [ТС]     Приоритет преобразований внутри if #16
Я, на самом деле, после добавления operator void* не сразу заметил, что все остальные преобразования объявлены как const, а в новом не указал.
Поэтому и возник вопрос "почему void*, а не bool внутри if".
Потом, правда, всё стало на свои места. Так что
Цитата Сообщение от 0x10 Посмотреть сообщение
Указатель может быть приведен к булу. И это нормально, на этом преобразование заканчивается.
как бы не тот случай.
Yandex
Объявления
23.07.2013, 13:47     Приоритет преобразований внутри if
Ответ Создать тему
Опции темы

Текущее время: 18:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru