# explicit in C++ なんとなく知っているC++のexplicit装飾子について再確認する。 ## 明示的な型変換 たとえば `1 + 0.5` のような計算をするとき、intとdoubleの値の足し算なので型が異なる。 しかしいちいちコンパイルエラーになっていると大変なので、多くの場合暗黙に型変換をしてくれ、このケースだと1が0.5浮動小数点型に変換されて計算される。 暗黙でない型変換とは、例えば`(double)(1)`みたいなやつ。static_castなどを用いてcastする場合は明示的な型変換。 他にも型変換演算子を持つ場合、そのオペランドが呼ばれるときは明示的な型変換となる。 例えば `if(x)` のようにif文を使う場合この中の値は明示的にbool値に変換されている。なので、xの値がboolへの型変換演算子を持つオブジェクトなら明示的な変換に成功する。 本来このような型変換は暗黙的な呼び出しでも呼ばれるが、explicit装飾子をつけることで明示的な変換でのみ呼び出されることを保証できる。 ## 具体例 explicitがついているケースについて具体例を見ながら確認。 以下の例を考える。 ```cpp= struct X { explicit operator bool() const { return true; } }; constexpr X x {}; ``` OKなケースとコンパイルエラーになるケースを例示してみる。[参考](https://cpprefjp.github.io/lang/cpp11/explicit_conversion_operator.html) ```cpp= // OKな例 // キャストによる明示的な型変換 bool ok1 = (bool)x; bool ok2 = static_cast<bool>(x); bool ok3 = bool(x); bool ok4 = !x; bool ok5 = !!x; // 否定演算子2回でboolに明示的に変換 bool ok6 = x && true; // if文や条件演算子による型変換は明示 bool ok7 = x ? true : false; if (x) {} // コンパイルエラー // boolへの暗黙変換なので無理 bool bad1 = x; // bool値との比較も暗黙の型変換 bool bad2 = x == true; ``` ## explicitコンストラクタ Chromiumでは引数が1つあるコンストラクタにはexplicitをつけるべしというスタイルガイドがある。[Implicit Conversions](https://google.github.io/styleguide/cppguide.html#Implicit_Conversions) の章を参照。 explicitにマークすることで1引数のときにコピーコンストラクタとごっちゃになる不慮の事故を防いでくれる。 例えばこんなケース。[参考](https://stackoverflow.com/questions/121162/what-does-the-explicit-keyword-mean) ```cpp= class String { public: String(int n) { std::cout << "int" << std::endl; } String(const char p) { std::cout << "char" << std::endl; } }; int main(void) { String mystring = 'x'; return 0; } ``` このとき'x'がなんなのかわからない。ただの文字かもしれないし、暗黙的に変換されたintになるかもしれない。 一応このケースだとconst charのほうが優先されるが、もしこれがなければエラーなくintのほうが選択されるし、そもそも言語仕様として決まってるのかよくわからない。 explicitをつければ、もっとわかりやすいので、想定と違うやつやっちゃうことがない。 なお引数が2個以上の場合はどちらでもいいっぽい。 これは、もともと必要なかったがinitializer_listによる初期化の導入で必要になった。今の所initializer_listによる初期化はあまり使用されていないので、別にいいかってことかな?