Насколько явным должен быть при вызове конструктора?
У меня этот класс
struct foo
{
explicit foo(const std::uint32_t& x, const std::uint32_t& y);
};
и метод
int main()
{
std::int32_t x = -1;
std::int32_t y = -1;
foo f(x, y);
}
В моем компиляторе (MSVC2012) он компилируется и запускается со значениями x
и y
, обернутыми в беззнаковые типы. Я не ожидал этого, но ожидал ошибку компиляции из-за несоответствующих типов.
Что мне не хватает?
Ответы
Ответ 1
Вам не повезло, стандарт позволяет неявное преобразование подписанного в unsigned посредством создания анонимного временного аргумента, переданного константной ссылкой.
(Обратите внимание, что это неверно для непостоянной ссылки).
Если вы используете С++ 11, лучше всего удалить конструктор, используя
foo(const std::int32_t& x, const std::int32_t& y) = delete;
Pre С++ 11 вы можете сделать этот конструктор private
и не определять его. Скорее, как старомодные непереписываемые идиомы.
MSVC2012 - это своего рода компилятор С++ 03/С++ 11 на полпути. Он реализует некоторые функции С++ 11, но не другие. К сожалению, удаление конструкторов является одной из функций, которые она поддерживает не, поэтому подход private
isation является наилучшим доступным для вас способом.
Ответ 2
Собственно, вы должны использовать новый синтаксис синтаксиса foo f{x, y}
, который, по крайней мере, выдает предупреждение. После этого вы можете настроить свой компилятор для обработки предупреждений как ошибок и обрабатывать их соответственно, так как хороший код обычно должен также избавляться от предупреждений (потому что если вы хотели, чтобы преобразование произошло, вы должны были использовать Явное литье).
Ответ 3
explicit
не препятствует неявному преобразованию с аргументами конструктора (что явно имеет место при связывании ссылок); он предотвращает неявное построение.
void bar(foo);
int main()
{
foo f({0, 0}); // doesn't matter that the arguments are implicitly converted
bar({0, 0}); // error - implicit conversion required here to pass a foo
bar(f); // crucially, ok because argument requires no conv. construction
}