0

I'm not sure what the terminology to use here is, which is making finding information about it difficult. After this surprised me in my code (hit compile, realized I forgot to update a few places... it compiled anyway and ran without error), I made simple example to verify it with.

I have a container class that contains another class. It has a constructor that takes a const reference to the class it contains. I have another function that takes a const reference to the container class. I can pass the function an instance of the contained class, and it creates a temporary of the container class for me automatically. No warnings, either (-Wall -pedantic -Wextra -Werror).

#include <iostream>

class A { // Contained class.
public:
    A(int i) : a_number_(i) {}
    void print() const { std::cout << a_number_ << "\n"; }
private:
    int a_number_;
};

class A_Container { // Container class.
public:
    ~A_Container() { delete a_; }
    A_Container(const A& a) : a_(new A(a)) { std::cout << "I was called!\n"; }
    const A& getA() const { return *a_; }
private:
    A* a_;
};

void foo(const A_Container& container) { // This func takes a container...
    container.getA().print();
}

int main() {
    A a(147);
    foo(a); // ...but I'm passing it the contained class.
    return 0;
}

Output:

I was called!
147

What is this called? What are the requirements for this type of conversion to work?

I can see that it makes sense for this to work, but is there more to it than compiler magic?

EDIT:

Useful link: What does the explicit keyword mean?

Claytorpedo
  • 179
  • 2
  • 13

1 Answers1

2

C++ will implicitly construct the container class for you if it has a single-argument constructor not marked explicit. To avoid this happening by accident, it is common to qualify unary constructors as explicit:

explicit Container(const A& a);

Now it won't compile (which in some cases is an improvement, to avoid accidentally "working" code if it is actually wrong or undesirable).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436