Check if template argument is inherited from class
I want to check if the type given to a template is inherited from a base class in my project.
It should work like one would expect it from the following example:
template< class T : public CBaseClass >
- Is it p开发者_开发技巧ossible to do this with templates, if not, how else can I do it?
Following an example from Stroustrup:
template<class Test, class Base>
struct AssertSameOrDerivedFrom {
AssertSameOrDerivedFrom() { &constraints; }
public:
static void constraints() {
Test *pd = 0;
Base *pb = pd;
}
};
template<class T>
struct YourClass {
YourClass() {
AssertSameOrDerivedFrom<T, CBaseClass>();
}
};
In C++0x, this becomes:
template<class T>
struct YourClass {
static_assert(std::is_base_of<CBaseClass, T>::value);
};
You can use boost::is_base_and_derived
from Boost, combined with BOOST_STATIC_ASSERT
. If you are using a compiler with TR1 or C++0x support, there are equivalents of those constructs in the standard library (std::is_base_of, and the static_assert statement in C++0x).
If you want to assert, do it Nurk's way. If you want to check, use is_base_of from boost or C++0x. If you can't use either of those, use SFINAE:
template < typename Base, typename PotentialDerived >
struct is_base
{
typedef char (&no) [1];
typedef char (&yes) [2];
static yes check(Base*);
static no check(...);
enum { value = sizeof(check(static_cast<PotentialDerived*>(0))) == sizeof(yes) };
};
The simplest solution seems to be std::is_base_of
:
static_assert(std::is_base_of_v<CBaseClass, T>);
You can of course also use it in combination with if constexpr
:
if constexpr (std::is_base_of_v<CBaseClass, T>) {
//
} else {
//
}
See cppreference for more details:
https://en.cppreference.com/w/cpp/types/is_base_of
Shorter is better:
template <typename Base, typename Derived>
struct is_base {
constexpr static bool check(Base*) { return true; }
constexpr static bool check(...) { return false; }
enum { value = check(static_cast<Derived*>(0)) };
};
Example 1:
struct A {};
struct B : A { };
int main(void) {
static_assert(is_base<A,B>::value, "If Error: A is not base of B");
}
Example 2:
template <bool, typename T=void>
struct Use {
static std::string info() { return "Implementation that consider that A is not base of B"; }
};
template <typename T>
struct Use<true,T> {
static std::string info() { return "Implementation that consider that A is the base of B"; }
};
int main(void) {
std::cout << Use<is_base<A,B>::value>::info(); //Implementation that consider that A is the base of B
}
精彩评论