Подтвердить что ты не робот

Почему компилятор выбирает строку bool поверх строки для неявного приведения типа L ""?

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

Мы имели

setValue( const std::wstring& name, const std::wstring& value );

std::wstring avalue( func() );
setValue( L"string", avalue );
std::wstring bvalue( func2() ? L"true", L"false" );
setValue( L"bool", bvalue );
setValue( L"empty", L"" );

Он был изменен так, что при сохранении значения bool мы используем те же строки (внутреннее хранение данных строк)

setValue( const std::wstring& name, const std::wstring& value );
setValue( const std::wstring& name, const bool& value );

std::wstring avalue( func() );
setValue( L"string", avalue );
setValue( L"bool", func2() );
setValue( L"empty", L"" ); << --- this FAILS!?!

Проблема с L "" заключается в том, что она неявно выполняет кастинг и раньше была счастлива как std:: wstring, но не предпочитает быть bool. Компилятор MSVC не жалуется и не предупреждает об этом, поэтому я беспокоюсь, что даже если я "исправлю" setValue (L "empty", L ""); быть

setValue( L"empty", std::wstring() );

кто-то другой может прийти позже и просто использовать setValue (L "empty", L ""); и вам придется отследить эту проблему еще раз.

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

4b9b3361

Ответ 1

Во-первых, причина этой проблемы: С++ Standard 13.3.3.2 определяет порядок преобразований. В нем говорится, что пользовательская последовательность преобразований хуже стандартной последовательности преобразования. Что происходит в вашем случае, так это то, что строковый литерал претерпевает логическое преобразование (определено в 4.12. Это стандартное преобразование). Он не использует преобразованное пользователем преобразование в std::wstring, которое было бы необходимо, если бы оно перешло в другую перегрузку.

Я бы рекомендовал просто изменить имя одной из перегрузок или добавить перегрузку, которая принимает строковый литерал напрямую (используя тип параметра wchar_t const*).

Ответ 2

L "" является указателем на широкую строку символов. Компилятор считает, что преобразование в bool имеет приоритет перед преобразованием в std:: wstring.

Чтобы устранить проблему, введите новый setValue:

void setValue(std::wstring const& name, const wchar_t * value);

Ответ 3

Поскольку bool является встроенным типом, предпочтительным является преобразование из wchar_t в bool. Я бы сказал, что самым простым решением является добавление перегрузки, которая принимает массив wchar_t и явно размещается там:

setValue( const std::wstring& name, const wchar_t s[] )
{
     setValue(name, wstring(s));
}

Ответ 4

Чтобы упростить бит, следующий код

#include <iostream>
using namespace std;

void f(const string &s)
{  cout << "string version called" << endl;  }

void f(const bool &b)
{  cout << "bool version called" << endl;  }

int main()
{  f("Hello World");  }

печатает " bool версия называется". Вы уверены, что ваш код выходит из строя только с пустой строкой?

Ответ 5

Вы можете заставить новую функцию взять какой-то другой тип, чем bool - возможно, просто прокси для bool - который не является конвертируемым из строки. Но на самом деле я просто переименую функцию bool-принятия и сделаю с ней.