Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use of incomplete types in templates

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'.

like image 250
jwezorek Avatar asked Oct 31 '25 14:10

jwezorek


1 Answers

The code is ill-formed, no diagnostic required.

[temp.res.general]/6.4

The 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.

like image 145
HolyBlackCat Avatar answered Nov 02 '25 05:11

HolyBlackCat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!