2
class Base {};

template <class T, typename = typename std::enable_if<std::is_base_of<Base, T>::value>::type>
class B {};                                                ^^^^^^^^^^ error C2139: 'A': an undefined class is not allowed as an argument to compiler intrinsic type trait '__is_base_of'

class A : public Base
{
    B<A> b;
};

Apparently this is not allowed. Is there a workaround, or something I'm forgetting?

6
  • 3
    I can immediately come up with a solution to the actual problem, but either way you're going to want to change the default argument value to typename std::enable_if<...>::type. Commented Feb 18, 2020 at 13:01
  • Why would I do that? Commented Feb 18, 2020 at 13:38
  • 2
    @T.J.Evers std::enable_if itself will never SFINAE out, it's its type member that is dynamically disabled. Commented Feb 18, 2020 at 13:46
  • 1
    Also, typo in my original comment: "I can ..." should have been "I can't ..." :). Commented Feb 18, 2020 at 13:51
  • 1
    Current workaround: us B<A, void> b; to bypass the detection. Not pretty, but at least it's still active everywhere else. Commented Feb 18, 2020 at 14:02

1 Answer 1

2

Here's the output for GCC:

type_traits:1302:66: error: incomplete type 'A' used in type trait expression
    : public integral_constant<bool, __is_base_of(_Base, _Derived)>
                                                                 ^
<source>:5:51: note: in instantiation of template class 'std::is_base_of<Base, A>' requested here
template <class T, typename = std::enable_if<std::is_base_of<Base, T>::value>>
                                                  ^
<source>:10:5: note: in instantiation of default argument for 'B<A>' required here
    B<A> b;
    ^~~~

<source>:8:7: note: definition of 'A' is not complete until the closing '}'
class A : public Base
      ^

Indeed, A is incomplete until the closing } has been reached. You use A in the type traits while instantiating B<A> inside A, so you're out of luck there.

What you can do instead is to enforce it with a static_assert in a member function of B:

template <class T>
class B {
public:
    B() {
        static_assert(std::is_base_of<Base, T>::value, "T must inherit from base");
    }
};

Inside member functions, all types are complete.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.