0
#include <bits/stdc++.h>
using namespace std;
class A {
    int x;
public:
    class B {
    public:
        int y;
        B(int _y) : y(_y) {}
        explicit operator A() const {
            return A(y);
        }
    };
    explicit A (int _x) : x(_x) {}
    explicit A (const A& o) : x(o.x) {} 
};
typedef unsigned int size_type;
int main () { 
    return 0;
}

Error: g++ -Wall -I./ -I/home/abdelrahman/main-repo/ -o "testt" "testt.cpp" (in directory: /home/abdelrahman/Desktop)

testt.cpp: In member function ‘A::B::operator A() const’: testt.cpp:11:14: error: no matching function for call to ‘A::A(A)’ return A(y); ^

Compilation failed.

  • Move the constructor to be before `class B`? – NathanOliver Jun 09 '17 at 15:54
  • See this question for example, explicit copy constructors tend to disallow return by value: https://stackoverflow.com/questions/4153527/explicit-copy-constructor-behavior-and-practical-uses – Mark B Jun 09 '17 at 15:57
  • fyi: If you remove the explicit from As copy constructor it compiles. Now looking at why. – Richard Critten Jun 09 '17 at 15:57
  • More thoughts: is there any point in making the copy constructor `explicit`? Usual reasons for `explicit` is to avoid unintended conversions, converting (copying) an `A` to another `A` seems safe to me. And `=delete` can now be used to disable copy construction if required. – Richard Critten Jun 09 '17 at 16:05
  • @RichardCritten you are right there's no need for that, but i'm just curious about the reason behind this error. – Abdelrahman Ramadan Jun 09 '17 at 16:09
  • 3
    Don't include . –  Jun 09 '17 at 16:31

1 Answers1

1

Marking the copy constructor explicit means that the compiler isn't allowed to use it implicitly, and that is what happens when the function returns – there's an implicit use of the copy constructor when the return value is copied "out of" the function.

The same happens when you pass an argument – the compiler implicitly uses the copy constructor for creating the argument.

The following is a minimal example which fails for those reasons:

class A
{
public:
    A(){}
    explicit A(const A&){}
};

void g(A a)
{

}

A f()
{
    A a;
    return a; // Fails; no suitable constructor
}

int main()
{
    A a;
    g(a); // Fails; no suitable constructor
}

The only copies you can make are explicit copies – ones where the source code explicitly copies an object, such as

A a;
A b(a);  // Succeeds because this is an explicit copy.

There is little point in using explicit on anything except converting constructors.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • what do you mean by implicit copies ?! and where does returning a value make implicit conversions ? shouldn't it just call the copy constructor with explicit parameter of type `A`. Also I think there's something else wrong in your code defining another constructors deletes the default constructor so you shouldn't use it in the return line `A()` or you can define it yourself. – Abdelrahman Ramadan Jun 09 '17 at 16:20