Приоритеты специализации шаблона при использовании указателей или ссылок - PullRequest
2 голосов
/ 08 декабря 2010

У меня есть класс сериализатора, подобный этому:

class Serializer
{
public:
    // Func 1 (default)
    template <class T>
    void Serialize(T* pValue)
    {
        SerializeInternal(reinterpret_cast<char*>(pValue), sizeof(*pValue));
    }

    // Func 2 (specialization)
    template <> 
    void Serialize<Serializable>(Serializable* pSerializable)
    {
        pSerializable->Serialize(*this);
    }

protected:

    // Implemented by input and output serializers
    virtual void SerializeInternal(char* pData, size_t size) = 0;
};

Теперь моя проблема в том, что когда у меня есть классы, которые наследуют интерфейс Serializable, они всегда будут обрабатываться Func 1, даже если я хочу, чтобы они обрабатывались Func 2 (указатели или ссылки не имеют значения, они оба ведут себя одинаково). Похоже, что C ++ не распознает, что интерфейс Serializable наследуется, если вы явно не укажете, что:

SerializableClass sc; // Inherits Serializable
InputSerializer s; // Inherits Serializer

s.Serialize(&sc); // Func 1 is called >:(
s.Serialize<Serializable>(&sc); // Func 2 is called

Теперь, как только я забуду добавить <Serializable> куда-нибудь, программа, конечно, выдает ошибку, что довольно раздражает.

Есть ли способ обойти это?

Ответы [ 3 ]

1 голос
/ 08 декабря 2010

Кажется, что C ++ не распознает, что интерфейс Serializable наследуется, если вы явно не укажете, что

Это правда. Если у вас есть класс

class SerializableClass : public Serializable

только SerializableClass, а не Serializable, учитывается при определении параметра T.

Если вам нужно создать две функции, одну с любым указателем, другую с указателем на что-либо, производное от Serializable, вы можете создать две перегрузки и использовать SFINAE, чтобы выбрать более узкую, когда это возможно.

template <class T>
typename boost::enable_if_c<!boost::is_base_of<Serializable, T>::value, void>::type foo(T*) { ... }

template <class T>
typename boost::enable_if<boost::is_base_of<Serializable, T>, void>::type foo(T*) { ... }

Если вы не хотите использовать boost, вы можете реализовать необходимые функции, подобные this .

0 голосов
/ 08 декабря 2010

Я нашел ссылку, объясняющую, как работает boost::is_base_of: Как работает `is_base_of`?

Видимо, они используют довольно причудливую магию шаблон-фу, чтобы заставить его работать. Я могу «легко» написать подобную функцию самостоятельно.

Если вы не достаточно умны, чтобы решить это самостоятельно, посмотрите на плюсы;)

0 голосов
/ 08 декабря 2010

Используйте перегрузку вместо шаблона специализации!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...