Mastrem
Mastrem

Reputation: 225

How to determine if a type is derived from a template class at compile time?

Say I have some template classes:

template<class T>
class Foo{}

template<class T>
class Bar{}

Now, I want to make sure (at compile-time) that the type used in Bar is derived from Foo. I already found this answer that shows how to do it at runtime, but I would like to check at compile-time, maybe using static_assert or something.
Is there a way to do this?

Upvotes: 2

Views: 134

Answers (1)

skypjack
skypjack

Reputation: 50550

Now, I want to make sure (at compiletime) that the type used in Bar is derived from Foo.

You can do something like this:

#include<type_traits>
#include<utility>

template<class T>
class Foo{};

template<typename T>
std::true_type test(const Foo<T> &);

std::false_type test(...);

template<class T>
class Bar {
    static_assert(decltype(test(std::declval<T>()))::value, "!");
};

struct S: Foo<int> {};

int main() {
    Bar<S> ok1;
    Bar<Foo<int>> ok2;
    // Bar<int> ko;
}

See it on wandbox.
The basic idea is that you can bind a temporary of type T to const Foo<U> & if T is derived from a specialization of Foo, no matter what's U. Therefore you can declare (no definition required) a couple of functions like the ones in the example to test it, then use the declared return type in a static_assert or any other constant context.


Edit

As suggested by @Quentin in the comments, probably it's worth replacing the reference with a pointer to prevent false positives from conversion constructors and operators.

Upvotes: 7

Related Questions