Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Заставить работать operator bool 
V
    Опции темы
borisbn
Дата 18.11.2013, 13:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Здравствуйте!
Имеется такой код:
Код
class Stmt {
public:
    Stmt( sqlite3 * db, const std::string & sql ) {
        m_ok = ( sqlite3_prepare( db, sql.c_str(), -1, & m_stmt, 0 ) == SQLITE_OK );
    }
    ~Stmt() {
        sqlite3_finalize( m_stmt );
    }
    operator sqlite3_stmt*() { std::cout << "pointer" << std::endl; return m_stmt; }
    operator bool() const { std::cout << "bool" << std::endl; return m_ok; }

private:
    sqlite3_stmt * m_stmt;
    bool m_ok;
};

http://ideone.com/YBnKoU
Оператор приведения к sqlite3_stmt* мне нужен, чтобы передавать экземпляр класса Stmt в C-шные функции. Типа такого:
Код
Stmt stmt( db, someSelectRequest );
sqlite3_bind_int( stmt, 1, 42 ); // (1)

Оператор приведения к bool мне нужен, чтобы после создания экземпляра проверять, всё ли в порядке. Типа такого:
Код
Stmt stmt( db, someSelectRequest );
if ( stmt ) { ... } // (2)

На MinGW и g++ первая конструкция отрабатывает (и отрабатывает правильно), а вторая - нет. Т.е. не совсем нет. Оно компилируется, но вместо оператора приведения к bool вызывается первый оператор.
Попытки явного приведения типа, такие как
Код
if ( (bool)stmt )
и
if ( bool( stmt ) )

ни к какому результату не привели.
Вопрос: можно ли что-то сделать (доработать класс, задать ключи компиляции и т.д.), чтобы в (2) вызывался оператор bool, а в (1) - оператор приведения к sqlite3_stmt* ?
Спасибо.

P.S. Просьба не предлагать кидать исключение в конструкторе и не выделыватся, а написать ф-цию isOk(), которую и вызывать. Это и так понятно ))
------------------------------------------------------------------------
Как принято на некоторых других форумах, привожу решение от baldina в самом вопросе - нужно убрать const у operator bool:
Код
operator bool() /* const */ { ... };


Это сообщение отредактировал(а) borisbn - 18.11.2013, 14:33


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 18.11.2013, 14:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



http://ideone.com/n9oPXe

Добавлено через 3 минуты и 12 секунд
короче заведи себе 2 bool() - const и не const
PM MAIL   Вверх
vinter
Дата 18.11.2013, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Код

explicit operator sqlite3_stmt*() { std::cout << "pointer" << std::endl; return m_stmt; }
explicit operator bool() const { std::cout << "bool" << std::endl; return m_ok; }

По идее, должно хватить explicit для bool. Для кода выше нужен современный компилятор.

Это сообщение отредактировал(а) vinter - 18.11.2013, 14:23


--------------------
Мой блог
PM MAIL WWW   Вверх
borisbn
Дата 18.11.2013, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Вау... Как оперативно! Спасибо большое!

Кстати, сначала подумал, что Вы меня дурачите - не увидел разницы между моим кодом и Вашим ))
И ещё. Можно в догонку вопрос - Вы уже сталкивались с таким или ткнули пальцем в небо ? М.б. стандарт чётко говорит по этому поводу ? Если последнее, то не могли бы Вы подсказать, где именно ?
Ещё раз спасибо.
Закрываю

Добавлено через 1 минуту и 24 секунды
vinter, неа. explicit не спасает.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 18.11.2013, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



все просто: компилятор использует const версию только для констант.
про стандарт не скажу, лениво искать. 
PM MAIL   Вверх
vinter
Дата 18.11.2013, 14:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата

vinter, неа. explicit не спасает.

Не может этого быть. При explicit sqlite3_stmt* компилятор не может использовать этот оператор в if
Цитата

все просто: компилятор использует const версию только для констант.

Компилятор не может использовать неконстантную версию для константы, но при обратной ситуации он не испытывает проблем. Более того, по идее, он должен предпочитать именно константную версию для lvalue

Добавлено через 9 минут и 30 секунд
Здесь хорошо этот вопрос раскрыт с указанием необходимых частей стандарта


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 18.11.2013, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(vinter @  18.11.2013,  14:55 Найти цитируемый пост)
При explicit sqlite3_stmt* компилятор не может использовать этот оператор в if

почему? Stmt преобразуется в sqlite3_stmt* (implicit user-defined conversion), указатель - в bool (implicit standard conversion).

Цитата

4.
2 [Note: expressions with a given type will be implicitly converted to other types in several contexts:
...
— When used in the condition of an if statement or iteration statement (6.4, 6.5). The destination type is bool

Цитата

4.12
1. An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.

Цитата

13.3.3.1.2 User-defined conversion sequences
1 A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined
conversion (12.3) followed by a second standard conversion sequence


раз уж полез в стандарт, отвечу на вопрос borisbn: в стандарте нет неявного преобразования из const в неконстантное значение.

это логично: иначе вообще зачем константы. представьте, что operator bool() родит побочный эффект. тогда результат выполнения в результате неявного преобразования непредсказуем.

Добавлено через 4 минуты и 50 секунд
а, я читаю неправильно
Цитата(vinter @  18.11.2013,  14:55 Найти цитируемый пост)
При explicit sqlite3_stmt*

все верно. если оператор должен вызываться явно, в неявном преобразовании он не участвует.

Добавлено через 8 минут и 21 секунду
Цитата(vinter @  18.11.2013,  14:55 Найти цитируемый пост)
он должен предпочитать именно константную версию для lvalue

ну это, увы, не так, хотя иногда кажется удобным: на одно преобразование больше получается.
и раз хочется, что бы оба преобразования выполнялись неявно, нужна неконстантная версия operator bool()

Добавлено через 10 минут и 17 секунд
Цитата(borisbn @  18.11.2013,  14:30 Найти цитируемый пост)
vinter, неа. explicit не спасает. 

http://ideone.com/CMl6xv
к указателю в этом случае приходится приводить явно
PM MAIL   Вверх
vinter
Дата 18.11.2013, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Цитата(baldina @  18.11.2013,  16:16 Найти цитируемый пост)
http://ideone.com/CMl6xvк указателю в этом случае приходится приводить явно

Не обязательно: int * t{p};

Добавлено @ 15:54
Цитата(baldina @  18.11.2013,  16:16 Найти цитируемый пост)
ну это, увы, не так, хотя иногда кажется удобным: на одно преобразование больше получается.

Да, я не прав. Всё это регулируется следующей строкой стандарта([over.ics.rank]p3):
Цитата

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
...
S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.



Это сообщение отредактировал(а) vinter - 18.11.2013, 15:59


--------------------
Мой блог
PM MAIL WWW   Вверх
borisbn
Дата 18.11.2013, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



vinter, спасибо за ссылку на СОшку. Там aschepler очень подробно всё объяснил. Ключевым моментом является то, что для const-версии требуется на одно преобразование больше (Stmt -> const Stmt), а раз больше, то выбирается то, где меньше.
Ещё раз всем спасибо.

Цитата(vinter @  18.11.2013,  15:46 Найти цитируемый пост)
Не обязательно: int * t{p}; 

В реальности мне нужно не присваивать указателю, а передавать мой объект в функцию:

Цитата(borisbn @  18.11.2013,  13:44 Найти цитируемый пост)
Код
Stmt stmt( db, someSelectRequest );
sqlite3_bind_int( stmt, 1, 42 ); // (1)




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
borisbn
Дата 18.11.2013, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



На самом деле не
Цитата(borisbn @  18.11.2013,  15:55 Найти цитируемый пост)
для const-версии требуется на одно преобразование больше

т.к. для версии с указателем нужно его ещё потом к bool приводить.

Ох и сложный же язык...


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
vinter
Дата 18.11.2013, 16:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 13
Всего: 56



Нет, при перегрузке никаких двойных преобразований не рассматривается. У тебя, по сути две функции: 
Код

operator sqlite3_stmt*(Stmt& obj) { std::cout << "pointer" << std::endl; return obj.m_stmt; }
operator bool(const Stmt& obj) { std::cout << "bool" << std::endl; return obj.m_ok; }

Теперь перечитываем вышеприведенную цитату. У нас как раз случай, что S1(operator sqlite3_stmt) больше подходит, т.к. S2(operator bool) имеет const.

Это сообщение отредактировал(а) vinter - 18.11.2013, 16:27


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 18.11.2013, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



да, user-defined преобразование лишь одно
Цитата

A well-formed implicit conversion sequence is one of the following forms:
— a standard conversion sequence (13.3.3.1.1),
— a user-defined conversion sequence (13.3.3.1.2), or
— an ellipsis conversion sequence (13.3.3.1.3).
...
A user-defined conversion sequence consists of an initial standard conversion sequence followed by a user-defined conversion (12.3) followed by a second standard conversion sequence

а дальше все подходящие преобразования ранжируются, и выбирается лучшее.
"на одно преобразование больше" это скорее фольклор, а не стандарт, хотя фольклор "правильный", т.к. длина преобразования неявно влияет на приоритет преобразования. Учитывая, что преобразование лишь одно, разная длина может означать только наличие преобразования квалификаторов (такое преобразование (surprise!) тоже является стандартным).

Для квалификаторов кстати есть таблица
Цитата

3.9.3 CV-qualifiers
5 Table 7: relations on const and volatile
no cv-qualifier < const
no cv-qualifier < volatile
no cv-qualifier < const volatile
const < const volatile
volatile < const volatile

хотя наш случай в п. 13.3.3.2 указан явно, и даже имеется пример
Цитата

[ Example:
int f ( const int *);
int f ( int *);
int i ;
int j = f (& i ); / / Calls f(int*)
— end example ]


ЗЫ. Кажется сам стал лучше понимать, откуда дети берутся что взялось smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0585 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.