A template method call that allows only subclasses as a parameter

Suppose I have a set of classes inherited from a single superclass S:

class S{ ... };

class C1 : public S{ ... };
class C2 : public S{ ... };

Then suppose I have a boilerplate method:

template<class T> void foo(T* instance);

I would like to statically verify that foo is never called by providing an instance of the superclass, but only the caller, providing one of the (specific) subclasses (e.g. explicitly calling foo<C1>(x), for example)

Is it possible?

+4
source share
1 answer

First we can write a tag to check if it is obtained Tfrom S, but not S:

template <class Base, class Derived>
using is_strict_base = 
    std::integral_constant<bool,
        std::is_base_of<Base,Derived>::value && 
        !std::is_same<Base,typename std::remove_cv<Derived>::type>::value>;

You can use std::enable_ifto use this feature:

template<class T>
typename std::enable_if<is_strict_base<S,T>::value>::type
foo(T* instance)
{}

++ 14 std::enable_if_t, :

template<class T>
std::enable_if_t<is_strict_base<S,T>::value>
foo(T* instance)
{}

- static_assert:

template<class T>
void foo(T* instance)
{
    static_assert(is_strict_base<S,T>::value, 
                  "T must be derived from S, but not S");
}

, , .

+10

Source: https://habr.com/ru/post/1606387/


All Articles