The following C++11 code compiles successfully on my GCC 4.8:
struct NonStack
{
private:
NonStack() = default;
public:
static NonStack* Create(){
return new NonStack;
}
};
NonStack a;
int main() { }
However the following gives a compilation error:
struct NonStack
{
private:
NonStack(){}
};
NonStack a;
int main() { }
Why does the first one succeed? Shouldn't the private defaulted constructor prohibit creation of an object via NonStack a;?
This is gcc bug 54812, the compiler fails to respect access specifiers for explicitly defaulted special member functions. Bug 56429, which is marked as a duplicate of the earlier one, has a test case that is almost identical to the example in the question.
The solutions are to upgrade to gcc4.9, which resolves the issue. Or create an empty body for the constructor, instead of explicitly defaulting it, as you've done in the second example.
Related
I have code like this:
class A{
public:
int b;
};
int main()
{
A a{.b = 5};
}
And the program compiles.
However, when I add another class and I make A inherit that class (like below), it throws an error "no matching function for call to ‘A::A()’" (or "No matching constructor for initialization of A").
class C{
};
class A: public C{
public:
int b;
};
int main()
{
A a{.b = 5};
}
Why?
You are using feature "Designated initializers" which is available since C++20.
Also I can't reproduce this issue: https://godbolt.org/z/fz3PeP
note with C++17 gcc and clang just file an warning, msvc file an error
with C++20 it is fine on all three (msvc needs c++latest option).
with C++14 it files error everywhere
So looks like problem is just compiler version or configuration
struct sa
{
struct sb { int a = 123;};
inline static sb b;
};
The above code generates an error:
main.cpp:25:20: error: default member initializer for ‘sa::sb::a’ required before the end of its enclosing class
inline static sb b;
^
main.cpp:24:21: note: defined here
struct sb { int a = 123;};
^~~~~~
Removing the inline keyword or the default member initializer works. But just from the output, I don't understand why this usage is wrong.
I think this code is correct and should be accepted; gcc and clang are erring on the side of caution in order to avoid the defect of Core Issue 1397.
That issue ruled that a program is ill-formed if a NSDMI (non-static data member initializer) causes the class's defaulted default constructor to be generated.
However your code doesn't do that. The NSDMI is just an integer literal. The example that prompted this issue had code like int a = ( (sa(), 123) );
What I guess might be happening is: The standard also says that , when processing the NSDMI, the class sa should be treated as complete. So perhaps the compilers are deferring the NSDMI processing until after the closing brace of sa is reached; and then flagging the error because inline static sb b; would generate sb::sb().
Possibly the standard is still defective and nobody thought of your example until now.
As a workaround you can explicitly provide the troublesome constructor:
struct sb { int a = 123; sb() {} };
Compiling following code gives "undefined reference to `A::~A()":
#include <cstdlib>
#include <memory>
template <typename T>
struct A {
A() {}
~A() {}
};
struct Aggregate {
using key_vector = A<char>;
using value_vector = A<int>;
value_vector vals;
key_vector keys;
};
int
main()
{
auto x = malloc(sizeof(Aggregate));
new (x) Aggregate{};
return 0;
}
the problem is present on clang 7.0 and 6.0 (possibly also some oolder versions). See: https://godbolt.org/z/GNPk3V
On newer clang versions and on gcc it works fine.
Is this expected or is it some kind of bug in clang?
This appears to be Bug 28280, fixed by https://reviews.llvm.org/D45898:
If an initializer in a braced-init-list is a C++ class that has a non-trivial destructor, mark the destructor as referenced. This fixes a crash in CodeGenFunction::destroyCXXObject that occurs when it tries to emit a call to the destructor on the stack unwinding path but the CXXRecordDecl of the class doesn't have a CXXDestructorDecl for the destructor.
This example does use a braced-init-list and emits the destructor call right before calling _Unwind_Resume. The destructor is not trivial. Changing the initialization to use () instead of {} makes the error go away because it's no longer initialized with a braced-init-list. The destructor call in my comment would presumably cause the destructor to be marked as referenced. Perhaps enabling optimization plays with the same things that make this appear only for non-trivial destructors.
Clang warns (when using -Weverything or Wglobal-constructors) about constructors for static objects.
warning: declaration requires a global constructor
[-Wglobal-constructors]
A A::my_A; // triggers said warning
^~~~
Why is this relevant and how should one deal with this warning?
Simple example code:
class A {
// ...
static A my_A;
A();
};
A A::my_A; // triggers said warning
Here is a simpler case that triggers the same warning:
class A {
public:
// ...
A();
};
A my_A; // triggers said warning
test.cpp:7:3: warning: declaration requires a global constructor [-Wglobal-constructors]
A my_A; // triggers said warning
^~~~
1 warning generated.
This is perfectly legal and safe C++.
However for every non-trivial global constructor you have, launch time of your application suffers. The warning is simply a way of letting you know about this potential performance problem.
You can disable the warning with -Wno-global-constructors. Or you can change to a lazy initialization scheme like this:
A&
my_A()
{
static A a;
return a;
}
which avoids the issue entirely (and suppresses the warning).
Solution from #Howard Hinnant avoid global constructor, but it do exit time destructor still.
It can be found with option -Wexit-time-destructors
So Ideal solution can be based on CR_DEFINE_STATIC_LOCAL from http://src.chromium.org/svn/trunk/src/base/basictypes.h
A& my_A()
{
static A &a = *new A;
return a;
}
If you can declare the constructor constexpr, that will suppress the warning (because this guarantees constant initialization). See https://godbolt.org/z/s3hY83jdr
I was surprised by the fact that GCC does not consider the call to foo() in the following program ambiguous:
#include <iostream>
struct B1 { bool foo(bool) { return true; } };
struct B2 { bool foo(bool) { return false; } };
struct C : public B1, public B2
{
using B1::foo;
using B2::foo;
};
int main()
{
C c;
// Compiles and prints `true` on GCC 4.7.2 and GCC 4.8.0 (beta);
// does not compile on Clang 3.2 and ICC 13.0.1;
std::cout << std::boolalpha << c.foo(true);
}
The above function call compiles and returns true on GCC 4.7.2 and GCC 4.8.0 (beta), while it won't compile (as I would expect) on Clang 3.2 and ICC 13.0.1.
Is this a case of "no diagnostic required", or is it a bug in GCC? References to the C++11 Standard are encouraged.
§7.3.3/3:
In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined; otherwise it introduces the set of declarations found by member name lookup (10.2, 3.4.3.1).
¶14:
… [ Note: Two using-declarations may introduce functions with the same name and the same parameter types. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed.
¶16:
For the purpose of overload resolution, the functions which are introduced by a using-declaration into a
derived class will be treated as though they were members of the derived class.
So, the using declarations are legal, but the functions are peers in the same overload set, as you said, and the program is ill-formed.
The call to foo(true) in your program is, as you say, clearly ambiguous; furthermore, it is ambiguous according to the algorithm presented in §10.2 and consequently, it should be flagged on use. (Flagging the using declaration would be incorrect; 10.2(1) clearly states that ambiguous uses of names are flagged on lookup, not on declaration.)
It's interesting to contrast this program with a similar one, which is the subject of a a recognized gcc bug (slightly modified from that bug report to make the parallel clearer):
#include <iostream>
struct A {
static int foo() {return 1;}
static int foo(char) { return 2;}
};
struct B1 : A {
// using A::foo;
};
struct B2 : A {
// using A::foo;
};
struct C : B1, B2 {
// using B1::foo;
// using B2::foo;
};
int main()
{
std::cout << C::foo();
}
The above program is correct; despite the diamond inheritance, foo is a static member of A, so it is not ambiguous. In fact, gcc compiles it without trouble. However, uncommenting the two instances of using A::foo, which does not change anything about either foo, causes gcc to produce the oddly reduplicated error noted in the bug report. Uncommenting the two using declarations inside C, which presumably triggers the other bug which is the subject of this question, then masks the static function bug and causes the program to compile again.
clang seems to handle all possible variants of this program, for what it's worth.
Finally, note that an explicitly declared foo(bool) within C (in the original program) will win out over any foo(bool) brought into C's scope by using declarations. I suspect that both of these bugs are the result of bad bookkeeping while trying to keep track of the various function declarations in each class's scope and their individual provenance (as a sequence of using declarations and function declarations).