The following bit of code fails to compile on gcc 7.3.0 and clang 6.0.0 (but seems to compile fine under MSVC):
#include <utility>
struct IncompleteType;
template<typename T>
struct Container {
T value;
};
using Uninstantiatable = Container<IncompleteType>;
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
throw 1;
}
The error I get is this:
<source>:7:7: error: field has incomplete type 'IncompleteType'
T value;
^
<source>:12:24: note: in instantiation of template class 'Container<IncompleteType>' requested here
auto foo() -> decltype(static_cast<Uninstantiatable const&>(std::declval<Uninstantiatable const&>())) {
^
<source>:3:8: note: forward declaration of 'IncompleteType'
struct IncompleteType;
^
1 error generated.
Compiler returned: 1
Try it yourself here: https://godbolt.org/g/5AW37K
However, it compiles if I replace line 10 by
using Uninstantiatable = IncompleteType;
Like @Jarod42 mentioned, it compiles again if you remove the definition of Container: http://godbolt.org/g/ue9iwC It looks like gcc and clang therefore only instantiate the template class if it is defined.
In both cases, I'm simply trying to copy a const-ref to a const-ref, so I expect that to work regardless of what the type is, and this indeed works if the type itself is incomplete. Does the standard specify that a template instantiation is triggered here, or are gcc and clang incorrect in their behavior?
Note that the pattern in the code above is taken from the std::is_constructible implementation of gcc, and the error was triggered when I tried to copy a tuple containg a const ref of a templated class with an incomplete type parameter, so yes, this happens in practice.
According to the standard implicit class template instantiation should only be performed when a complete object is required [temp.inst]/1:
[...], the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
As pointed out in Jarod's comment, if a definition for container
is not provided, Unintatiable is, independently of the completeness of InCompleteType
, an incomplete type and the code compile. Moreover this static_cast is obviously independent of the completness of the object. So I think this is a compiler bug of gcc and clang.
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