I have this test case:
struct A{ protected: A(){} }; struct B: A{}; struct C: A{ C(){} }; struct D: A{ D() = default; }; int main(){ (void)B{}; (void)C{}; (void)D{}; }
Both gcc and clang compile it in C++11 and C++14 mode. Both fail in C++17 mode:
$ clang++ -std=c++17 main.cpp main.cpp:7:10: error: base class 'A' has protected default constructor (void)B{}; ^ main.cpp:1:22: note: declared protected here struct A{ protected: A(){} }; ^ main.cpp:9:10: error: base class 'A' has protected default constructor (void)D{}; ^ main.cpp:1:22: note: declared protected here struct A{ protected: A(){} }; ^ 2 errors generated. $ clang++ --version clang version 6.0.0 (http://llvm.org/git/clang.git 96c9689f478d292390b76efcea35d87cbad3f44d) (http://llvm.org/git/llvm.git 360f53a441902d19ce27d070ad028005bc323e61) Target: x86_64-unknown-linux-gnu Thread model: posix
(clang compiled from master Branch 2017-12-05.)
$ g++ -std=c++17 main.cpp main.cpp: In function 'int main()': main.cpp:7:10: error: 'A::A()' is protected within this context (void)B{}; ^ main.cpp:1:22: note: declared protected here struct A{ protected: A(){} }; ^ main.cpp:9:10: error: 'A::A()' is protected within this context (void)D{}; ^ main.cpp:1:22: note: declared protected here struct A{ protected: A(){} }; ^ $ g++ --version g++ (GCC) 8.0.0 20171201 (experimental) Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Is this change of behavior part of C++17 or is it a bug in both compilers?
Protecting a constructor prevents the users from creating the instance of the class, outside the package. During overriding, when a variable or method is protected, it can be overridden to other subclass using either a public or protected modifier only. Outer class and interface cannot be protected.
Modifiers public, protected and, private are allowed with constructors. We can use a private constructor in a Java while creating a singleton class.
Constructor may be private. Show activity on this post. In your code, the program cannot run since you have defined a constructor and it is private. Therefore, in your current code, there is no way to create objects of the class, making the class useless in a sense.
Constructors cannot be declared in protected section of the class.
The definition of aggregate changed since C++17.
no base classes
no
virtual, private, or protected (since C++17)
base classes
That means, for B
and D
, they're not aggregate type before C++17, then for B{}
and D{}
, value-initialization will be performed, then the defaulted default constructor will be called; which is fine, because the protected
constructor of base class could be called by derived class's constructor.
Since C++17, B
and D
become aggregate type (because they have only public
base class, and note that for class D
, the explicitly defaulted default constructor is allowed for aggregate type since C++11), then for B{}
and D{}
, aggregate-initialization will be performed,
Each
direct public base, (since C++17)
array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.If the number of initializer clauses is less than the number of members
and bases (since C++17)
or initializer list is completely empty, the remaining membersand bases (since C++17)
are initializedby their default initializers, if provided in the class definition, and otherwise (since C++14)
by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
That means the base class subobject will be value-initialized directly, the constructor of B
and D
are bypassed; but the default constructor of A
is protected
, then the code fails. (Note that A
is not aggregate type because it has a user-provided constructor.)
BTW: C
(with a user-provided constructor) is not an aggregate type before and after C++17, so it's fine for both cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With