Почему T(const bool)
имеет приоритет над T(const std::string&)
при построении t
?
""
типа char[1]
;это неявно преобразуется в char const*
через преобразование массива в указатель.Указатель неявно преобразуется в bool
, причем все ненулевые указатели становятся true
, а все нулевые указатели становятся false
.Оба являются «встроенными» стандартными преобразованиями.
Преобразование char const* -> std::string
является объявленным пользователем преобразованием: оно использует конструктор преобразования std::string
, который принимает char const*
.
Стандартные («встроенные») преобразования предпочтительнее, чем объявленные пользователем преобразования при разрешении перегрузки, поэтому конструктор, принимающий bool
, здесь лучше, чем конструктор, принимающий std::string
.
Пока единственное, что я нашел, - это добавление еще одного конструктора
Это звучит как разумное решение;безусловно, самое простое решение для простого сценария, который вы описываете.Хотя вы используете присвоение *this
немного неуклюже;было бы лучше, чтобы оба конструктора делегировали какую-то функцию инициализации.
В качестве альтернативы вы можете использовать шаблон с enable_if
для любых конструкторов, для которых вы хотите запретить преобразования:
template <typename U>
T(U, std::enable_if<std::is_same<U, bool>::value>::type* = 0) { }
Этот конструктор будет вызываться только с аргументом bool
и ничем иным.Вы можете найти enable_if
и is_same
в Boost, C ++ TR1 или C ++ 0x.Вы также можете использовать !is_pointer
, is_integral
или какую-либо другую комбинацию признаков типа, чтобы учесть некоторые другие типы аргументов, но не char const*
.
Или, в качестве другой альтернативы, вы можете отказаться от bool
в целом и используйте свое собственное перечисление с перечислителями, соответствующими true
и false
для конструктора.То, имеет ли это смысл, зависит от вашего варианта использования.
Объявление explicit T(const bool)
во избежание не решает вышеуказанную проблему ... почему форма T t("")
все еще разрешена и вызывает T(const bool)
?
explicit
запрещает только неявные преобразования в T
.T t("");
вообще не имеет преобразований в T
;он напрямую инициализирует объект t
, создавая его с аргументом ""
, передаваемым какому-либо конструктору, наиболее подходящему.