Is a template for inheritance-based template specialization possible?

So, one pattern of the problem that I constantly encounter and do not have a good solution is how to provide specialized patterns based on what type the pattern parameter is determined from. For example, suppose I have:

template<typename T>
struct implementPersist;

template<typename T>
void persist( T& object )
{
   implementPersist::doPersist( object );
}

I would like for persist users to be able to provide implementation implementations of Persist :: persist for types declared after the above. This is straightforward in principle, but cumbersome in practice, but the user needs to provide a Persist implementation for each type.

To be more clear, suppose I have:

struct Persistent { virtual void myPersist() = 0; };
struct MyClass : public persistent { virtual void MyPersist() { ...implementation...} };

// Persists subclasses of Persistent using myPersist
template<>
struct implementPersist<Persistent>{ void doPersist(Persistent& p) { p->myPersist(); } };

struct X{};

template<>
struct implementPersist<X>{ void doPersist(X& p) { ...implementation...} };


// Persists subclasses of Persistent using boostPersist
struct MyBoostPersistedObject { virtual void boostPersist() = 0 };
struct Z : public MyBoostPersistedObject { virtual void boostPersist() = 0 };

template<>
struct implementPersist<myBoostPersistedObject>{ void boostPersist() { ...implementation... } };

, Persist, myBoostPersistedObject , (, POD). , ,

implementPersist<Persistent>::doPersist

if: persist (T &) , T . () , T = myClass. , . , , , , , .

void persist (Persistent &);  void persist (X &);  void persist (myBoostPersistedObject &);

, , .

- - :

class persist;

template<typename T, bool hasMyPersistMethod=isDerivedFrom(T,persist)::value >
struct implementPersist;

template<typename T, bool true >
struct implementPersist<T,true>
{
   template<> struct implementPersist<X>{ void doPersist(T& p) { p->myPersist(); } }
};

(. isDerivedFrom).

, implementPersist , . - .

, .

?

+3
2

, , enable_if.

#include <iostream>
#include <boost/type_traits.hpp>
using namespace std;


template <bool Enable, typename T = void>
struct enable_if
{
    typedef T type;
};

template <typename T>
struct enable_if<false, T>
{
};

template <typename T, typename Enable = void>
struct persist_t {};

struct A
{
    virtual void foo() const = 0;
};

template <typename T>
struct persist_t<T, typename enable_if<boost::is_base_of<A, T>::value>::type>
{
    static void persist(T const& x)
    {
        x.foo();
    }
};


struct B : A
{
    virtual void foo() const { cout << "B::foo\n"; }
};

template <typename T>
void persist(T & x)
{
    persist_t<T>::persist(x);
}

int main()
{
    B b;
    persist(b);
}

Boost enable_if, . Boost , .

, .

+3

:

MyClass x(...);
Persistent * p = &x;
implementPersist<Persistent> ip;
ip.doPersist(*p);
0

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


All Articles