From a previous question:
Doing a static_assert that a template type is another template
Andy Prowl provided me with this code that allows me to static_assert
that a template type is another template type:
template<template<typename...> class TT, typename... Ts>
struct is_instantiation_of : public std::false_type { };
template<template<typename...> class TT, typename... Ts>
struct is_instantiation_of<TT, TT<Ts...>> : public std::true_type { };
template<typename T>
struct foo {};
template<typename FooType>
struct bar {
static_assert(is_instantiation_of<foo,FooType>::value, ""); //success
};
int main(int,char**)
{
bar<foo<int>> b;
return 0;
}
This works great.
But this does not work for a subclass of foo<whatever>
:
template<template<typename...> class TT, typename... Ts>
struct is_instantiation_of : public std::false_type { };
template<template<typename...> class TT, typename... Ts>
struct is_instantiation_of<TT, TT<Ts...>> : public std::true_type { };
template<typename T>
struct foo {};
template<typename FooType>
struct bar {
static_assert(is_instantiation_of<foo,FooType>::value, ""); //fail
};
//Added: Subclass of foo<int>
struct foo_sub : foo<int> {
};
int main(int,char**)
{
bar<foo_sub> b; //Changed: Using the subclass
return 0;
}
Can Andy Prowl's is_instantiation_of
code be extended to allow for subclasses?
As KerrekSB wrote in his answer, an equally general extension of the solution you posted cannot be achieved.
However, if it is OK for you to give up a bit of genericity, you can write a type trait specific for foo
(exploiting the fact that derived-to-base is one of the few conversions that are performed during type deduction):
#include <type_traits>
template<typename T>
struct foo {};
template<typename T>
constexpr std::true_type test(foo<T> const&);
constexpr std::false_type test(...);
template<typename T>
struct is_instantiation_of_foo : public decltype(test(std::declval<T>())) { };
You would then use it like so:
template<typename FooType>
struct bar {
static_assert(is_instantiation_of_foo<FooType>::value, "");
};
struct foo_sub : foo<int> {
};
int main(int,char**)
{
bar<foo_sub> b; // Will not fire
return 0;
}
Here is a live example.
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