Ответ 1
Традиционная мудрость заключается в том, что конструкторы, принимающие один параметр (явно или эффективно с использованием параметров по умолчанию), должны быть отмечены explicit
, если только они не определяют преобразование (std::string
, будучи конвертируемым из const char*
, одним из примеров последний). Вы сами выяснили причины, в которых неявные преобразования действительно могут сделать жизнь сложнее, чем она должна быть.
Возможно, очевидным исключением является конструктор копирования. Или, возможно, другим способом является рассмотрение того, что большинство типов конвертируются из и для себя, и что как таковой конструктор копирования не выделяется explicit
большую часть времени.
Хотя может показаться, что маркировка всех других конструкторов explicit
не повредит, я бы возразил против этого. Поскольку while explicit
не влияет на конструктор, принимающий несколько аргументов в С++ 03, это имеет эффект в С++ 11. Поместить его в код:
struct foo {
explicit foo(int i);
foo(int i, int j);
explicit foo(int i, int j, int k);
};
foo make_foo()
{
/* Not C++11-specific: */
// Error: no conversion from int to foo
return 42;
// Okay: construction, not conversion
return foo(42);
// Okay: constructions
return foo(42, 42);
return foo(42, 42, 42);
/* C++11 specific: */
// Error: no conversion from int to foo
return { 42 };
// Not an error, not a conversion
return { 42, 42 };
// Error! Constructor is explicit
return { 42, 42, 42 };
// Not an error, direct-initialization syntax
return foo { 42, 42, 42 };
}
Я лично считаю ненужным подробное описание того, что в функции, возвращающей foo
, я должен явно возвращать foo { 42, 42, 42 }
. Я не понимаю, от чего меня защищает explicit
. Я действительно хочу, чтобы синтаксис { initializers... }
имел в виду "построить объект из заданных инициализаторов", а explicit
попадает в путь, сохраняя при этом меня из ничего. (Так как { i }
действительно сводится к i
в контексте инициализации копирования - большую часть времени - я с удовольствием отдам это.)
Итак, я бы сказал, привыкнуть использовать explicit
для унарных конструкторов и только тех.