Search code examples
c++c++17default-constructorexplicit

Why adding `explicit` to a defaulted copy constructor prevents returning an object?


Considering this MRE (the real case involves some class with some inheritance and some member variables)

class A {
    public:
    
    A() = default;
    explicit A(const A&) = default;
    // explicit A(A&) = default; ///Adding this serves no purpose
    explicit A(A&&) = default;
    A& operator=(const A&) = default;
    A& operator=(A&&) = default;
};

auto dummy_a() {
    A a;
    return a; //no matching function for call to 'A::A(A)'
}

int main() {
    const auto a = dummy_a();
}

I get the following error unless I remove explicit from either the copy or the move constructor. (Can be tested here)

main.cpp: In function 'auto dummy_a()':
main.cpp:14:12: error: no matching function for call to 'A::A(A)'
   14 |     return a; //no matching function for call to 'A::A(A)'
      |            ^
main.cpp:4:5: note: candidate: 'constexpr A::A()'
    4 |     A() = default;
      |     ^
main.cpp:4:5: note:   candidate expects 0 arguments, 1 provided

Why is that the case?


Solution

  • In your function dummy_a your return value requires implicit copy construction

    auto dummy_a() {
        A a;
        return a; // implicit 'A::A(A)'
    }
    

    If you indeed want your copy constructor to be explicit then this should be modified to

    auto dummy_a() {
        A a;
        return A{a}; // explicit 'A::A(A)'
    }