递归使用赋值运算符

时间:2014-12-28 23:14:10

标签: c++ variable-assignment operator-keyword

有人可以告诉我为什么递归operator=没有在这里编译?任务很简单。我有一个Menu<T>类,其中T是菜单中每个选项的类型。 Menu<WeightedItem<T>>类只是Menu<T>的特化,其中WeightedItem<T>包含项T以及int数据成员(出于概率目的)。

我想通过使用其项目并附加一些概率权重(其值与问题无关)将Menu<T>转换为Menu<WeightedItem<T>>。问题是菜单可以有子菜单,而子菜单又可以有子菜单,因此我需要递归使用operator=。到目前为止,这是我的代码:

template <typename T> struct WeightedItem;

template <typename T>
struct Menu
{
    struct Option
    {
        const T item;
        Menu* submenu;
        Option* next;
        Option(const T& t, Menu<T>* menu = nullptr) 
            : item(t),
            submenu(menu),
            next(nullptr)
        {}
    };

    Option* first; // first option in the menu
};


template <typename T>
struct WeightedItem {
    T item;
    int probabilityWeight;
};

template <typename T>
struct Menu<WeightedItem<T>>
{
    struct Option
    {
        const WeightedItem<T> item;
        Menu* submenu;
        Option* next;
        Option(const WeightedItem<T>& t, Menu<WeightedItem<T>>* menu = nullptr)
            : item(t),
            submenu(menu),
            next(nullptr)
        {}
        Option& operator=(const Option& other)
        {
            // Needed for defining Menu& operator=(const Menu<T>&).
            if (this == & other)
                return *this;
            item = other.item;
            submenu = other.submenu;
            next = other.next;
            return *this;
        }
    };
    Option* first;
    Menu & operator=(const Menu<T>&);
};

template <typename T>
Menu<WeightedItem<T>>& Menu<WeightedItem<T>>::operator=(const Menu<T>& other)
{
    delete first;
    if (!other.first)
        first = nullptr;
    else
    {
        int weight = 1;
        Menu<WeightedItem<T>> submenu operator=(*other.first->submenu); // Recursive operator= call for submenus.  Won't compile.
        first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
        Option* current = first->next;
        for (typename Menu<T>::Option* o = other.first->next; o; o = o->next)
        {
            Menu<WeightedItem<T>> submenu operator=(*o->submenu); // Recursive operator= call for submenus.  Won't compile.
            current = new Menu<WeightedItem<T>>::Option({o->item, ++weight}, &submenu);
            current = current->next;
        }
    }
    return *this;
}

struct Item {};

int main() {
    Menu<Item> menu;
    Menu<WeightedItem<Item>> weightedMenu;
    weightedMenu = menu;
}

但这两个递归调用似乎是非法的。为什么呢?

[Error] expected initializer before 'operator'

如果是非法的,如何解决它?

更新: 好的,所有深度复制都是使用new进行的多次分配。我不得不简单地放弃operator = idea并简单地定义一个递归函数。我测试过结果也是准确的:

template <typename T> struct WeightedItem;

template <typename T>
struct Menu {
    struct Option {
        const T item;
        Menu* submenu;
        Option* next;
        Option (const T& t, Menu<T>* menu = nullptr): item(t), submenu(menu), next(nullptr) {}
    };
    Option* first = nullptr;
};


template <typename T>
struct WeightedItem {
    T item;
    int probabilityWeight;
};

template <typename T>
struct Menu<WeightedItem<T>> {
    struct Option {
        const WeightedItem<T> item;
        Menu* submenu;
        Option* next;
        Option (const WeightedItem<T>& t, Menu<WeightedItem<T>>* menu = nullptr): item(t), submenu(menu), next(nullptr) {}
    };
    Option* first = nullptr;
    inline void inheritFrom (const Menu<T>&);
};

template <typename T>
inline void Menu<WeightedItem<T>>::inheritFrom (const Menu<T>& other) {
    if (!other.first)
        first = nullptr;
    else {
        int weight = 1;
        Menu<WeightedItem<T>>* submenu = nullptr;
        if (other.first->submenu) {
            submenu = new Menu<WeightedItem<T>>;    
            submenu->inheritFrom (*other.first->submenu);  // Recursive call for submenus.
        }
        first = new Menu<WeightedItem<T>>::Option ({other.first->item, weight}, submenu);
        Option *current = first->next, *prev = first;
        for (typename Menu<T>::Option* o = other.first->next;  o;  o = o->next) {
            Menu<WeightedItem<T>>* submenu = nullptr;
            if (o->submenu) {
                submenu = new Menu<WeightedItem<T>>;
                submenu->inheritFrom (*o->submenu);  // Recursive call for submenus.
            }
            current = new Menu<WeightedItem<T>>::Option ({o->item, ++weight}, submenu);
            prev->next = current;
            if (o->next) {
                prev = current;
                current = current->next;
            }
        }
    }
}

struct Item {};

int main() {
    Menu<Item> menu;
    Menu<WeightedItem<Item>> weightedMenu;
    weightedMenu.inheritFrom(menu);
}

然而,关于使用=递归的原始问题仍未得到解答。而且似乎c ++不支持它,因为当我尝试使用=来翻译上面的内容时,它不会编译。

1 个答案:

答案 0 :(得分:2)

替换

   Menu<WeightedItem<T>> submenu operator=(*other.first->submenu);
   first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);

通过

   first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
   first->submenu->operator=(*other.first->submenu);

   first = new Menu<WeightedItem<T>>::Option({other.first->item, weight}, &submenu);
   *first->submenu = *other.first->submenu;

这是解决问题的起点,但真正的解决方案需要每个选项中的选项和子菜单的深层副本。