1引数コンストラクタ以外に対するexplicit指定

C++03では、ひとつの引数をとるコンストラクタで変換コンストラクタ以外に対してはexplicitを付ける、という慣習がありました (別の言い方をすると、パラメータ付き構築にexplicitを付ける)。

C++11では、波カッコ構文による「一様初期化 (Uniform Initialization)」と初期化子リストがあるので、少し事情が異なります。C++11では、explicitを付けたコンストラクタは、X x = {a, b, c};のような代入演算子を伴うリスト初期化が禁止されます。

struct X {
    X(int, int) {}
};

struct Y {
    explicit Y(int, int) {}
};

int main() {
    X x {1, 2}; // OK
    Y y {1, 2}; // OK

    X x2 = {1, 2}; // OK
//  Y y2 = {1, 2}; // error
}

そのため、1引数をとるコンストラクタにデフォルト引数をつけてデフォルトコンストラクタと実装をいっしょにすると、意図と違った挙動になる可能性があります。X x = {a, b, c};構文を許可するかも含めて、任意のコンストラクタにexplicitを付けるかどうかを検討しましょう。

struct A {
    A(int=0) {}
};

struct B {
    explicit B(int=0) {}
};

int main() {
    A a{}; // OK
    B b{}; // OK

    A a2 = {}; // OK
//  B b2 = {}; // error
}

例として、string(int pos, int len)みたいなコンストラクタは、explicitにしたほうがいいですね。