Функции шаблона-члена не могут быть виртуальными - обходной путь? - PullRequest
5 голосов
/ 12 ноября 2011

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

У меня есть код, похожий на этот:

struct Entity
{
    template<typename It>
    virtual It GetChildren(It it) { return it; }
};

struct Person : public Entity
{
    template<typename It>
    virtual It GetChildren(It it) { *it++ = "Joe"; }
};

struct Node : public Entity
{
    Node left, right;
    const char *GetName() { return "dummy"; }

    template<typename It>
    virtual It GetChildren(It it)
    {
        *it++ = left.GetName();
        *it++ = right.GetName();
        return it;
    }
};

Понятно, мне нужна динамическая отправка. Но, учитывая, что классы на самом деле довольно большие, я не хочу шаблонировать весь класс . И я все еще хочу поддерживать любой вид итератора.

Какой лучший способ добиться этого?

Ответы [ 3 ]

3 голосов
/ 12 ноября 2011

Если единственное, что вам нужно - это поддержка любого типа итератора, вы можете использовать итератор, который использует стирание типа. Я думаю, что any_iterator реализован где-то в Boost Sandbox / Vault или Adobe Labs или в одном из них. Вот первый результат от Google:

http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/any_iterator.html

2 голосов
/ 12 ноября 2011

Поскольку вы не хотите создавать шаблон для всего класса и не хотите использовать итератор с удалением типа, единственное решение - написать собственный итератор.

Кстати, ваш пример выглядит странно,Может быть, вы можете взглянуть на то, как улучшить дизайн, чтобы ваша проблема исчезла.

1 голос
/ 12 ноября 2011

Вы не хотите в общем «поддерживать любой тип итератора».

Вы хотите удовлетворить требования контейнера STL, чтобы предоставить итератор, который пользователи могут поддерживать в общем.Сделайте итератор, затем предоставьте итератор typedef для вашего контейнера:

class Entity_Iterator {
public:
    Entity_Iterator operator++() { /* et cetera */ }
    Entity& operator*() const { /* et cetera */ }
private:
    Entity* entity_ptr_;
    // et cetera
}

class Entity_Container {
public:
    typedef Entity_Iterator iterator;
    iterator begin() const { /* et cetera */ }
    iterator end() const  { /* et cetera */ }
private:
    Entity* head_;
    // et cetera
}

Теперь пользователь может следовать соглашению о контейнере STL для использования вашего контейнера, и вы сможете применять алгоритмы STL к своему контейнеру какскважина:

Entity_Container x;
Entity_Container::iterator i = x.begin();
i->GetName();

Редактировать добавить ссылку:

http://www.sgi.com/tech/stl/Container.html

Редактировать

Я пытаюсь найти ссылку на полный шаблон заглушки кода C ++ для реализации контейнера STL, который, как я помню, однажды видел, но для меня это очень сложно Шаблон STL .

Редактировать

Сделайте это так, и вы сможете написать свой контейнер в виде древовидной структурыкоторые могут содержать гетерогенные типы, унаследованные от Entity с помощью виртуальных методов. Похоже, вы пытаетесь это сделать?

Или, возможно, нет?

...