Why is my class non default-constructible? - c++

I have those classes:
#include <type_traits>
template <typename T>
class A {
public:
static_assert(std::is_default_constructible_v<T>);
};
struct B {
struct C {
int i = 0;
};
A<C> a_m;
};
int main() {
A<B::C> a;
}
When compiling, a_m is not default constructible but a is.
When changing C to:
struct C {
int i;
};
everything is fine.
Tested with Clang 9.0.0.

This is disallowed both by the text of the standard and by several major implementations as noted in the comments, but for completely unrelated reasons.
First, the "by the book" reason: the point of instantiation of A<C> is, according to the standard, immediately before the definition of B, and the point of instantiation of std::is_default_constructible<C> is immediately before that:
For a class template specialization, [...] if the specialization is
implicitly instantiated because it is referenced from within another
template specialization, if the context from which the specialization
is referenced depends on a template parameter, and if the
specialization is not instantiated previous to the instantiation of
the enclosing template, the point of instantiation is immediately
before the point of instantiation of the enclosing template.
Otherwise, the point of instantiation for such a specialization
immediately precedes the namespace scope declaration or definition
that refers to the specialization.
Since C is clearly incomplete at that point, the behavior of instantiating std::is_default_constructible<C> is undefined. However, see core issue 287, which would change this rule.
In reality, this has to do with the NSDMI.
NSDMIs are weird because they get delayed parsing - or in standard parlance they are a "complete-class context".
Thus, that = 0 could in principle refer to things in B not yet declared, so the implementation can't really try to parse it until it has finished with B.
Completing a class necessitates the implicit declaration of special member functions, in particular the default constructor, as C doesn't have a constructor declared.
Parts of that declaration (constexpr-ness, noexcept-ness) depend on the properties of the NSDMI.
Thus, if the compiler can't parse the NSDMI, it can't complete the class.
As a result, at the point when it instantiates A<C>, it thinks that C is incomplete.
This whole area dealing with delayed-parsed regions is woefully underspecified, with accompanying implementation divergence. It may take a while before it gets cleaned up.

Undefined behavior it is:
If an instantiation of a template above depends, directly or
indirectly, on an incomplete type, and that instantiation could yield
a different result if that type were hypothetically completed, the
behavior is undefined.

Related

Inheritance in derived class that is a partial specialization of class template [duplicate]

If the classes below were not templates I could simply have x in the derived class. However, with the code below, I have to use this->x. Why?
template <typename T>
class base {
protected:
int x;
};
template <typename T>
class derived : public base<T> {
public:
int f() { return this->x; }
};
int main() {
derived<int> d;
d.f();
return 0;
}
Short answer: in order to make x a dependent name, so that lookup is deferred until the template parameter is known.
Long answer: when a compiler sees a template, it is supposed to perform certain checks immediately, without seeing the template parameter. Others are deferred until the parameter is known. It's called two-phase compilation, and MSVC doesn't do it but it's required by the standard and implemented by the other major compilers. If you like, the compiler must compile the template as soon as it sees it (to some kind of internal parse tree representation), and defer compiling the instantiation until later.
The checks that are performed on the template itself, rather than on particular instantiations of it, require that the compiler be able to resolve the grammar of the code in the template.
In C++ (and C), in order to resolve the grammar of code, you sometimes need to know whether something is a type or not. For example:
#if WANT_POINTER
typedef int A;
#else
int A;
#endif
static const int x = 2;
template <typename T> void foo() { A *x = 0; }
if A is a type, that declares a pointer (with no effect other than to shadow the global x). If A is an object, that's multiplication (and barring some operator overloading it's illegal, assigning to an rvalue). If it is wrong, this error must be diagnosed in phase 1, it's defined by the standard to be an error in the template, not in some particular instantiation of it. Even if the template is never instantiated, if A is an int then the above code is ill-formed and must be diagnosed, just as it would be if foo wasn't a template at all, but a plain function.
Now, the standard says that names which aren't dependent on template parameters must be resolvable in phase 1. A here is not a dependent name, it refers to the same thing regardless of type T. So it needs to be defined before the template is defined in order to be found and checked in phase 1.
T::A would be a name that depends on T. We can't possibly know in phase 1 whether that's a type or not. The type which will eventually be used as T in an instantiation quite likely isn't even defined yet, and even if it was we don't know which type(s) will be used as our template parameter. But we have to resolve the grammar in order to do our precious phase 1 checks for ill-formed templates. So the standard has a rule for dependent names - the compiler must assume that they're non-types, unless qualified with typename to specify that they are types, or used in certain unambiguous contexts. For example in template <typename T> struct Foo : T::A {};, T::A is used as a base class and hence is unambiguously a type. If Foo is instantiated with some type that has a data member A instead of a nested type A, that's an error in the code doing the instantiation (phase 2), not an error in the template (phase 1).
But what about a class template with a dependent base class?
template <typename T>
struct Foo : Bar<T> {
Foo() { A *x = 0; }
};
Is A a dependent name or not? With base classes, any name could appear in the base class. So we could say that A is a dependent name, and treat it as a non-type. This would have the undesirable effect that every name in Foo is dependent, and hence every type used in Foo (except built-in types) has to be qualified. Inside of Foo, you'd have to write:
typename std::string s = "hello, world";
because std::string would be a dependent name, and hence assumed to be a non-type unless specified otherwise. Ouch!
A second problem with allowing your preferred code (return x;) is that even if Bar is defined before Foo, and x isn't a member in that definition, someone could later define a specialization of Bar for some type Baz, such that Bar<Baz> does have a data member x, and then instantiate Foo<Baz>. So in that instantiation, your template would return the data member instead of returning the global x. Or conversely if the base template definition of Bar had x, they could define a specialization without it, and your template would look for a global x to return in Foo<Baz>. I think this was judged to be just as surprising and distressing as the problem you have, but it's silently surprising, as opposed to throwing a surprising error.
To avoid these problems, the standard in effect says that dependent base classes of class templates just aren't considered for search unless explicitly requested. This stops everything from being dependent just because it could be found in a dependent base. It also has the undesirable effect that you're seeing - you have to qualify stuff from the base class or it's not found. There are three common ways to make A dependent:
using Bar<T>::A; in the class - A now refers to something in Bar<T>, hence dependent.
Bar<T>::A *x = 0; at point of use - Again, A is definitely in Bar<T>. This is multiplication since typename wasn't used, so possibly a bad example, but we'll have to wait until instantiation to find out whether operator*(Bar<T>::A, x) returns an rvalue. Who knows, maybe it does...
this->A; at point of use - A is a member, so if it's not in Foo, it must be in the base class, again the standard says this makes it dependent.
Two-phase compilation is fiddly and difficult, and introduces some surprising requirements for extra verbiage in your code. But rather like democracy it's probably the worst possible way of doing things, apart from all the others.
You could reasonably argue that in your example, return x; doesn't make sense if x is a nested type in the base class, so the language should (a) say that it's a dependent name and (2) treat it as a non-type, and your code would work without this->. To an extent you're the victim of collateral damage from the solution to a problem that doesn't apply in your case, but there's still the issue of your base class potentially introducing names under you that shadow globals, or not having names you thought they had, and a global being found instead.
You could also possibly argue that the default should be the opposite for dependent names (assume type unless somehow specified to be an object), or that the default should be more context sensitive (in std::string s = "";, std::string could be read as a type since nothing else makes grammatical sense, even though std::string *s = 0; is ambiguous). Again, I don't know quite how the rules were agreed. My guess is that the number of pages of text that would be required, mitigated against creating a lot of specific rules for which contexts take a type and which a non-type.
(Original answer from Jan 10, 2011)
I think I have found the answer: GCC issue: using a member of a base class that depends on a template argument.
The answer is not specific to gcc.
Update: In response to mmichael's comment, from the draft N3337 of the C++11 Standard:
14.6.2 Dependent names [temp.dep]
[...]
3 In the definition of a class or class template, if a base class depends on a
template-parameter, the base class scope is not examined during unqualified name
lookup either at the point of definition of the class template
or member or during an instantiation of the class template or member.
Whether "because the standard says so" counts as an answer, I don't know. We can now ask why the standard mandates that but as Steve Jessop's excellent answer and others point out, the answer to this latter question is rather long and arguable. Unfortunately, when it comes to the C++ Standard, it is often nearly impossible to give a short and self-contained explanation as to why the standard mandates something; this applies to the latter question as well.
The x is hidden during the inheritance. You can unhide via:
template <typename T>
class derived : public base<T> {
public:
using base<T>::x; // added "using" statement
int f() { return x; }
};

How to check that a C++ class is incomplete (only declared)?

I would like to write a C++ function that will check that its template parameter class is incomplete, so only class declaration is available but not full definition with all class members.
My function incomplete() looks as follows together with some demo program:
#include <type_traits>
#include <iostream>
template <typename T, typename V = void> constexpr bool is_incomplete = true;
template <typename T> constexpr bool is_incomplete<T, std::enable_if_t<sizeof(T)>> = false;
template <typename T> constexpr bool incomplete() { return is_incomplete<T>; }
struct A;
void print() { std::cout << incomplete<A>(); }
struct A {}; //this line affects GCC
int main()
{
print();
}
It works well in Clang printing 1, but in GCC the program prints 0 despite the fact that A class is incomplete in function print.
https://gcc.godbolt.org/z/qWW3hqbEv
Is GCC wrong here or there is a fault in my program?
Which compiler is correct is currently undecided. It's CWG Issue 1845.
The current wording of 13.8.4.1 [temp.point] does not define the point of instantiation of a variable template specialization. Presumably replacing the references to “static data member of a class template” with “variable template” in paragraphs 1 and 8 would be sufficient.
Given that issue is still in drafting stage (and no normative wording exists yet it the latest available draft), it remains unresolved. It isn't clear if a variable template can have multiple points of instantiation or not (though the direction the issue reporter suggests is clear).
For entities with multiple points of instantiation, the end of the translation unit is one as well. Also, if two points disagree on the definition of template, it's an ODR violation, plain and simple. GCC seems to provide two points, so you see the result of that. And I tend to agree with GCC here. A variable template is in many ways a shorthand for a static data member of a class template, and static data members do have multiple points of instantiation.
Either way, this is playing with the risk of nasal demons. Checking a type for complete-ness is not really possible reliably if that state can change in a TU (and possibly even if it can change in the entire program).
It looks like the finding whether a class is incomplete will be a violation of one definition rule (ODR) if at some point it becomes complete, so there should be no valid solution to the question.
Some more quotes from https://eel.is/c++draft/temp.point that I was suggested:
1 For a function template specialization ... the point of instantiation ... immediately follows the namespace scope declaration or definition that refers to the specialization.
7 A specialization for a function template ... may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,
for any such specialization that has a point of instantiation within the ... the translation-unit ..., the point after the ... [end of] the translation-unit is also considered a point of instantiation,
If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

Accessing protected data member of an abstract class template fail to compile [duplicate]

If the classes below were not templates I could simply have x in the derived class. However, with the code below, I have to use this->x. Why?
template <typename T>
class base {
protected:
int x;
};
template <typename T>
class derived : public base<T> {
public:
int f() { return this->x; }
};
int main() {
derived<int> d;
d.f();
return 0;
}
Short answer: in order to make x a dependent name, so that lookup is deferred until the template parameter is known.
Long answer: when a compiler sees a template, it is supposed to perform certain checks immediately, without seeing the template parameter. Others are deferred until the parameter is known. It's called two-phase compilation, and MSVC doesn't do it but it's required by the standard and implemented by the other major compilers. If you like, the compiler must compile the template as soon as it sees it (to some kind of internal parse tree representation), and defer compiling the instantiation until later.
The checks that are performed on the template itself, rather than on particular instantiations of it, require that the compiler be able to resolve the grammar of the code in the template.
In C++ (and C), in order to resolve the grammar of code, you sometimes need to know whether something is a type or not. For example:
#if WANT_POINTER
typedef int A;
#else
int A;
#endif
static const int x = 2;
template <typename T> void foo() { A *x = 0; }
if A is a type, that declares a pointer (with no effect other than to shadow the global x). If A is an object, that's multiplication (and barring some operator overloading it's illegal, assigning to an rvalue). If it is wrong, this error must be diagnosed in phase 1, it's defined by the standard to be an error in the template, not in some particular instantiation of it. Even if the template is never instantiated, if A is an int then the above code is ill-formed and must be diagnosed, just as it would be if foo wasn't a template at all, but a plain function.
Now, the standard says that names which aren't dependent on template parameters must be resolvable in phase 1. A here is not a dependent name, it refers to the same thing regardless of type T. So it needs to be defined before the template is defined in order to be found and checked in phase 1.
T::A would be a name that depends on T. We can't possibly know in phase 1 whether that's a type or not. The type which will eventually be used as T in an instantiation quite likely isn't even defined yet, and even if it was we don't know which type(s) will be used as our template parameter. But we have to resolve the grammar in order to do our precious phase 1 checks for ill-formed templates. So the standard has a rule for dependent names - the compiler must assume that they're non-types, unless qualified with typename to specify that they are types, or used in certain unambiguous contexts. For example in template <typename T> struct Foo : T::A {};, T::A is used as a base class and hence is unambiguously a type. If Foo is instantiated with some type that has a data member A instead of a nested type A, that's an error in the code doing the instantiation (phase 2), not an error in the template (phase 1).
But what about a class template with a dependent base class?
template <typename T>
struct Foo : Bar<T> {
Foo() { A *x = 0; }
};
Is A a dependent name or not? With base classes, any name could appear in the base class. So we could say that A is a dependent name, and treat it as a non-type. This would have the undesirable effect that every name in Foo is dependent, and hence every type used in Foo (except built-in types) has to be qualified. Inside of Foo, you'd have to write:
typename std::string s = "hello, world";
because std::string would be a dependent name, and hence assumed to be a non-type unless specified otherwise. Ouch!
A second problem with allowing your preferred code (return x;) is that even if Bar is defined before Foo, and x isn't a member in that definition, someone could later define a specialization of Bar for some type Baz, such that Bar<Baz> does have a data member x, and then instantiate Foo<Baz>. So in that instantiation, your template would return the data member instead of returning the global x. Or conversely if the base template definition of Bar had x, they could define a specialization without it, and your template would look for a global x to return in Foo<Baz>. I think this was judged to be just as surprising and distressing as the problem you have, but it's silently surprising, as opposed to throwing a surprising error.
To avoid these problems, the standard in effect says that dependent base classes of class templates just aren't considered for search unless explicitly requested. This stops everything from being dependent just because it could be found in a dependent base. It also has the undesirable effect that you're seeing - you have to qualify stuff from the base class or it's not found. There are three common ways to make A dependent:
using Bar<T>::A; in the class - A now refers to something in Bar<T>, hence dependent.
Bar<T>::A *x = 0; at point of use - Again, A is definitely in Bar<T>. This is multiplication since typename wasn't used, so possibly a bad example, but we'll have to wait until instantiation to find out whether operator*(Bar<T>::A, x) returns an rvalue. Who knows, maybe it does...
this->A; at point of use - A is a member, so if it's not in Foo, it must be in the base class, again the standard says this makes it dependent.
Two-phase compilation is fiddly and difficult, and introduces some surprising requirements for extra verbiage in your code. But rather like democracy it's probably the worst possible way of doing things, apart from all the others.
You could reasonably argue that in your example, return x; doesn't make sense if x is a nested type in the base class, so the language should (a) say that it's a dependent name and (2) treat it as a non-type, and your code would work without this->. To an extent you're the victim of collateral damage from the solution to a problem that doesn't apply in your case, but there's still the issue of your base class potentially introducing names under you that shadow globals, or not having names you thought they had, and a global being found instead.
You could also possibly argue that the default should be the opposite for dependent names (assume type unless somehow specified to be an object), or that the default should be more context sensitive (in std::string s = "";, std::string could be read as a type since nothing else makes grammatical sense, even though std::string *s = 0; is ambiguous). Again, I don't know quite how the rules were agreed. My guess is that the number of pages of text that would be required, mitigated against creating a lot of specific rules for which contexts take a type and which a non-type.
(Original answer from Jan 10, 2011)
I think I have found the answer: GCC issue: using a member of a base class that depends on a template argument.
The answer is not specific to gcc.
Update: In response to mmichael's comment, from the draft N3337 of the C++11 Standard:
14.6.2 Dependent names [temp.dep]
[...]
3 In the definition of a class or class template, if a base class depends on a
template-parameter, the base class scope is not examined during unqualified name
lookup either at the point of definition of the class template
or member or during an instantiation of the class template or member.
Whether "because the standard says so" counts as an answer, I don't know. We can now ask why the standard mandates that but as Steve Jessop's excellent answer and others point out, the answer to this latter question is rather long and arguable. Unfortunately, when it comes to the C++ Standard, it is often nearly impossible to give a short and self-contained explanation as to why the standard mandates something; this applies to the latter question as well.
The x is hidden during the inheritance. You can unhide via:
template <typename T>
class derived : public base<T> {
public:
using base<T>::x; // added "using" statement
int f() { return x; }
};

One static_assert makes another static_assert fail (is_default_constructible for inner class) [duplicate]

I have those classes:
#include <type_traits>
template <typename T>
class A {
public:
static_assert(std::is_default_constructible_v<T>);
};
struct B {
struct C {
int i = 0;
};
A<C> a_m;
};
int main() {
A<B::C> a;
}
When compiling, a_m is not default constructible but a is.
When changing C to:
struct C {
int i;
};
everything is fine.
Tested with Clang 9.0.0.
This is disallowed both by the text of the standard and by several major implementations as noted in the comments, but for completely unrelated reasons.
First, the "by the book" reason: the point of instantiation of A<C> is, according to the standard, immediately before the definition of B, and the point of instantiation of std::is_default_constructible<C> is immediately before that:
For a class template specialization, [...] if the specialization is
implicitly instantiated because it is referenced from within another
template specialization, if the context from which the specialization
is referenced depends on a template parameter, and if the
specialization is not instantiated previous to the instantiation of
the enclosing template, the point of instantiation is immediately
before the point of instantiation of the enclosing template.
Otherwise, the point of instantiation for such a specialization
immediately precedes the namespace scope declaration or definition
that refers to the specialization.
Since C is clearly incomplete at that point, the behavior of instantiating std::is_default_constructible<C> is undefined. However, see core issue 287, which would change this rule.
In reality, this has to do with the NSDMI.
NSDMIs are weird because they get delayed parsing - or in standard parlance they are a "complete-class context".
Thus, that = 0 could in principle refer to things in B not yet declared, so the implementation can't really try to parse it until it has finished with B.
Completing a class necessitates the implicit declaration of special member functions, in particular the default constructor, as C doesn't have a constructor declared.
Parts of that declaration (constexpr-ness, noexcept-ness) depend on the properties of the NSDMI.
Thus, if the compiler can't parse the NSDMI, it can't complete the class.
As a result, at the point when it instantiates A<C>, it thinks that C is incomplete.
This whole area dealing with delayed-parsed regions is woefully underspecified, with accompanying implementation divergence. It may take a while before it gets cleaned up.
Undefined behavior it is:
If an instantiation of a template above depends, directly or
indirectly, on an incomplete type, and that instantiation could yield
a different result if that type were hypothetically completed, the
behavior is undefined.

When is a C++ template instantiation type checked?

When compiling C++, gcc and clang seems to postpone the type-checking of template instantiations until after all declarations of the program have been processed. Is this guaranteed in the language?
To elaborate, I can keep a type incomplete at the point where a template is defined or a template instantiation is needed, as long as I complete the type somewhere later in the program:
class A;
class B;
extern A* pa;
// 1. template definition
template<typename T>
T* f() { return static_cast<T*>(pa); }
// 2. template instantiation
B* test() { return f<B>(); }
// 3. completing types
class A { };
class B : public A { };
Note that the definitions of A and B are required to type check the template instantiation (to make the static_cast valid). If you leave out step 3, step 2 will no longer compile.
In the organisation of my headers, can I rely that this order will be accepted by any standard C++ compiler?
The rule is called "two-phase name lookup".
The names, which are not dependant on the template parameters, are looked up and checked at definition, and the dependent names are checked at the point of instantiation.
For your example, there is one important detail: the end of translation unit is also considered a point of instantiation for function templates:
C++14 N4140 14.6.4.1 [temp.point] P8:
A specialization for a function template, a member function template, or of a member function or static
data member of a class template may have multiple points of instantiations within a translation unit, and
in addition to the points of instantiation described above, for any such specialization that has a point
of instantiation within the translation unit, the end of the translation unit is also considered a point of
instantiation.
Thus, although the type is incomplete at point "2", where explicit instantiation happens, it is complete at the end of file, which makes the template instantiation legitimate.
Note: Microsoft compiler does not implement this rule in full, violating the standard. In Microsoft compiler, all the lookup happens at the point of instantiation (thus the example should also work, but I don't have access to MSVC to check). Other major compilers do implement this rule correctly.