Вывод шаблона для типов POD и указателей - PullRequest
0 голосов
/ 07 октября 2018

Я работал над своим архиватором, который мне недавно пришлось переустанавливать.Он основан на этом архиваторе lib , который я нашел, но мне также пришлось добавить поддержку сериализации полиморфного объекта с помощью информации о его типе.Я пытался решить эту проблему с помощью шаблонного вывода, но это кажется неправильным.Я узнал, что использование дедукции добавляет сгенерированные методы к пулу перегрузки, но я ничего не нашел о том, можно ли перегрузить определениями шаблонов.

Вот фрагмент кода, который у меня есть:

class Archive {
    // ... ctor, and others

    // --- 
    template <class T>
    const Archive& operator<<(const T& v) const
    {
        *this & v;
        return *this;
    }

    template <class T>
    Archive& operator>>(T& v)
    {
        *this & v;
        return *this;
    }

    // --- 
    template <class T>
    Archive& operator&(T*& v)
    {
        Serializer::LoadObject(v);
        return *this;
    }

    template <class T>
    const Archive& operator&(const T*& v) const
    {
        Serializer::StoreObject(v);
        return *this;
    }

    template <class T>
    Archive& operator&(T& v)
    {
        v.Serialize(*this);
        return *this;
    }

    template <class T>
    const Archive& operator&(const T& v) const
    {
        ((T&)(v)).Serialize(*this);
        return *this;
    }

    // ... the rest of the implementation, serializers for POD, arrays and STL containers    
};

Основное использование это

struct SomePoco{
    int m_someMember;
    int m_someOtherMember;
    template<class AR> void Srerialize(AR&ar){
        ar & m_someMember & m_someOtherMember;
    }
};

, которое отлично работает.Если бы я использовал указатели объектов, это выглядело бы так - слишком упрощенно, не беспокойтесь о чистоте, просто для записи:

class SomeSerializableClass : public Serializable{
public:
    // ... some macros that adds Serializable implementations
    template<class AR> void Srerialize(AR&ar){
        ar & m_someMember & m_someOtherMember;
    }    
private:
    int m_someMember;
    int m_someOtherMember;
}

SomeSerializableClass *obj = new SomeSerializableClass();
Archive ar;
ar << obj;
// ... rest of the stuff

в этом случае я бы хотелЗвоните template <class T> const Archive& Archive::operator&(const T*& v) const за template <class T> const Archive& operator&(const T& v) const.Вывод происходит следующим образом: template <class T> const Archive& operator&(const T& v) const, где T = SomeSerializableClass *

Вопрос в следующем: - есть ли способ переопределить поведение этого вычета с помощью пользовательского правила вычета, или - есть ли способ отключить вычет длятипы указателей, чтобы я мог определять свои собственные операторные функции вне класса?

Обновление: Я прошел через type_trais , предложенное ниже и я совсем не понимаю что-то с этим.С таким типом черт, похоже, он не работает в Visual Studio 2017.

template <class T, class = class std::enable_if<std::is_class<T>>::type>
Archive& operator&(T& v)
{
    v.Serialize(*this);
    return *this;
}

template <class T, class = class std::enable_if<std::is_class<T>>::type>
const Archive& operator&(const T& v) const
{
    const_cast<T&>(v).Serialize(*this);
    return *this;
}

Я также консультировался с реализацией в VS;по спецификации is_object было бы хорошо для меня, потому что я ищу те объекты, которые имеют свои функции Serialize, являются ли они экземпляром класса или структуры.Тем не менее, is_object - это совершенно другая вещь в VS, чертой закрытия была is_class.

У вас, ребята, есть еще какие-нибудь предложения?

...