I have a template function and wish to ensure at compile time that it is not instantiated on a subtype or supertype of a particular class.
How can I cause a C++ compiler error if this is violated?
class base {
};
class derived : public base {
};
class lowest : public derived {
};
template <typename T>
bool isCorrect(const T& obj) {
typedef foo<T> D;
foo<T> *def = foo<T>::find();
return (def && def->getAnswer(object));
}
I want isCorrect
to only be available for class derived
, but not base
or lowest
. Note there could be many other lowest classes and a string of base classes to be excluded as well as alternative derived classes that are acceptable.
Is there a way in C++ to limit the template to only apply to the derived classes I explicitly specify?
Type traits, specifically is_base_of
.
#include <type_traits>
template <typename T>
bool isCorrect(const T& obj) {
static bool const is_base = std::is_base_of<base, T>::value;
static bool const derives = std::is_base_of<derived, T>::value;
// specify allowed types here
static bool const is_derived = std::is_same<T, derived>::value;
// ---
static_assert((!is_base && !derives) || is_derived, "wrong argument type");
typedef foo<T> D;
foo<T> *def = foo<T>::find();
return (def && def->getAnswer(object));
}
Note that this is C++11 specific, but you can get the same behaviour with Boost.TypeTraits.
Here's one technique that I know of.
First, make another template class policy_enforcer
. Declare this class without defining it, and also provide a specialization of it for derived
that is also defined:
template<typename T> struct policy_enforcer;
template<> struct policy_enforcer<derived> { };
Then, within the function you wish to lock down, include the expression sizeof(policy_enforcer<T>)
. Since sizeof
on incomplete types is a compilation error, this will prevent the code from compiling.
Updated with live code: using base
, using derived
, using lowest
.
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