Is it legal to use an incomplete type in a template if the type is complete when the template is instantiated?
As below
#include <iostream>
struct bar;
template <typename T>
struct foo {
    foo(bar* b) : b(b) {
    }
    
     void frobnicate() {
          b->frobnicate();
     }
     T val_;
     bar* b;
};
struct bar {
     void frobnicate() {
          std::cout << "foo\n";
     }
};
int main() {
    bar b;
    foo<int> f(&b);
    f.frobnicate();
    return 0;
}
Visual Studio compiles the above without complaining. GCC issues the warning invalid use of incomplete type 'struct bar' but compiles. Clang errors out with member access into incomplete type 'bar'.
The code is ill-formed, no diagnostic required.
[temp.res.general]/6.4The validity of a template may be checked prior to any instantiation.
The program is ill-formed, no diagnostic required, if:
...
— a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, ...
If you absolutely can't define bar before the template, there is a workaround: you can introduce an artifical dependency on the template parameter.
template <typename T, typename, typename...>
struct dependent_type {using type = T;};
template <typename T, typename P0, typename ...P>
using dependent_type_t = typename dependent_type<T, P0, P...>::type;
Then use dependent_type_t<bar, T> instead of bar.
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