explicit in details

    If you ask a C ++ programmer about the meaning of the keyword explicit, the majority will answer that this keyword is placed before the constructor declaration with one parameter (or with a large number of parameters, but when all parameters, starting from the second, have default values) and prevent implicit conversion types during initialization.


    class Simple {
    public:
        Simple(int a) : a_(a) {}
    private:
        int a_;
    };
    class SimpleExplicit {
    public:
        explicit SimpleExplicit(int a) : a_(a) {}
    private:
        int a_;
    };
    template <typename S>
    void someFunc(const S& s) {
    }
    int main(int, char**) {
        Simple s3 = 11;
        // SimpleExplicit se3 = 11; - COMPILE ERROR
        SimpleExplicit se3 = SimpleExplicit(11);
        someFunc<Simple>(11);
        // someFunc<SimpleExplicit>(11); - COMPILE ERROR
        someFunc<SimpleExplicit>(SimpleExplicit(11));
        return 0;
    }

    In the good old C ++ 03, the application scenarios for this keyword ended there, however, since C ++ 11, the scope of explicit has expanded: now it makes sense not only in constructors with one parameter, and even not only in constructors.


    In 2011, a standard initialization (uniform initialization) was added to the Standard, which should bring order to the zoo in ways to initialize objects, inherited C ++ from language C. I will not discuss in detail here about universal initialization, there are many detailed articles on this topic. easy to find by keywords. In a nutshell: objects are proposed to be initialized using curly brackets, in fact, this extension is so-called. aggregate initialization (aggregate initialization), inherited from the time of C.


    With the advent of universal initialization, explicitly found meaning for designers with 0.2.3 or more parameters:


    class Simple {
    public:
        Simple() : a_(0), b_(0) {}
        Simple(int a) : a_(a), b_(0) {}
        Simple(int a, int b) : a_(a), b_(b) {}
    private:
        int a_, b_;
    };
    class SimpleExplicit {
    public:
        explicit SimpleExplicit() : a_(0), b_(0) {}
        explicit SimpleExplicit(int a) : a_(a), b_(0) {}
        explicit SimpleExplicit(int a, int b) : a_(a), b_(b) {}
    private:
        int a_, b_;
    };
    template <typename S>
    void someFunc(const S& s) {
    }
    int main(int, char**) {
        Simple s4 = {};
        someFunc<Simple>({});
        // SimpleExplicit se4 = {}; - COMPILE ERROR
        SimpleExplicit se4 = SimpleExplicit{};
        // someFunc<SimpleExplicit>({}); - COMPILE ERROR
        someFunc<SimpleExplicit>(SimpleExplicit{});
        Simple s5 = {11};
        someFunc<Simple>({11});
        // SimpleExplicit se5 = {11}; - COMPILE ERROR
        SimpleExplicit se5 = SimpleExplicit{11};
        // someFunc<SimpleExplicit>({11}); - COMPILE ERROR
        someFunc<SimpleExplicit>(SimpleExplicit{11});
        Simple s6 = {11, 22};
        someFunc<Simple>({11, 22});
        // SimpleExplicit se6 = {11, 22}; - COMPILE ERROR
        SimpleExplicit se6 = SimpleExplicit{11, 22};
        // someFunc<SimpleExplicit>({11, 22}); - COMPILE ERROR
        someFunc<SimpleExplicit>(SimpleExplicit{11, 22});
        return 0;
    }

    In addition, starting with C ++ 11, the explicit keyword can also be applied to type conversion operators, also prohibiting their implicit call:


    class Simple {
    public:
        Simple() {}
        operator bool() const { return true; }
    };
    class SimpleExplicit {
    public:
        explicit SimpleExplicit() {}
        explicit operator bool() const { return true; }
    };
    int main(int, char**) {
        Simple s7{};
        bool b7 = s7;
        SimpleExplicit se7{};
        // bool be7 = se7; - COMPILE ERROR
        bool be7 = static_cast<bool>(se7);
        return 0;
    }

    In conclusion, I would like to recommend using universal initialization in any new C ++ code, and also explicitly declare explicit constructors at all times, unless the implicit conversion is semantically justified.


    Also popular now: