The C++ standard does not allow delegate constructors and member initializers in a single mem-initializer-list, yet the following code compiles fine with clang++ and g++.
#include <iostream>
class Shape {
public:
Shape();
};
class Circle : public Shape {
public:
std::string name;
Circle(std::string name);
};
Shape::Shape() {
std::cout << "Shape constructor" << std::endl;
}
Circle::Circle(std::string name) : Shape::Shape(), name(name) { /* <--- Expected an error here! */
std::cout << "Circle constructor" << std::endl;
}
int main() {
Circle c("my_circle");
std::cout << c.name << std::endl;
return 0;
}
The relevant quote from the C++ 20 standard is (emphasis mine):
(§11.10.2/6) A mem-initializer-list can delegate to another constructor of the constructor’s class using any class-or-decltype that denotes the constructor’s class itself. If a mem-initializer-id designates the constructor’s class, it shall be the only mem-initializer; the constructor is a delegating constructor, and the constructor selected by the mem-initializer is the target constructor.[...]
Did I misread the C++ standard? Do clang++ and g++ deviate from the standard here?
A delegating constructor calls another constructor in the same class.
For example, in:
struct Foo
{
Foo(int) : Foo("delegate") {} // #1
Foo(std::string) {} // #2
};
#1 and #2 are both constructors for Foo
, and constructor #1 delegates to constructor #2.
In your case, you have a class that is derived from another class, and in:
Circle::Circle(std::string name) : Shape::Shape(), name(name)
You are initializing the base Shape
portion of the Circle
object, by calling Shape
s default constructor. You then move on after that to finish initializing the rest of the members of the Circle
class. This is not a delegating constructor.