Reputation: 225
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
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