Могу ли я установить аргументы по умолчанию для функций C++, которые являются объединением

Как вы можете видеть в следующем коде, я пытаюсь использовать некоторые аргументы по умолчанию функции «инициализировать», которые являются объединением. Как изменить определение функции «инициализировать», чтобы сделать ее совместимой с С++ до С++ 11? Нужно ли добавлять некоторые конструкторы в RedBlackPointer? Если да, то как?

template <typename T> class RedBlackNode{
protected:
    union RedBlackPointer{
        RedBlackNode *node;
        struct{
            unsigned value:1;   // for color / other info
        }flag;
    }left, right, parent;

    T key;

public:
    void initialize(T key, RedBlackPointer left = {(RedBlackNode*)0},
            RedBlackPointer right = {(RedBlackNode*)0},
            RedBlackPointer parent = {(RedBlackNode*)0}){
        this->key = key;
        this->left = left; this->right = right;
        this->parent = parent;
    }
}

person Firas    schedule 21.03.2015    source источник
comment
У вас нет ошибки в этом коде? Я думаю, что вы хотите хранить указатель node и value одновременно, поэтому вам не следует использовать объединение для этой цели.   -  person ciechowoj    schedule 21.03.2015
comment
Возможно, это поможет.   -  person ciechowoj    schedule 21.03.2015
comment
ISO C++03 8.5.1[dcl.init.aggr]/15: когда объединение инициализируется с помощью инициализатора, заключенного в фигурные скобки, фигурные скобки должны содержать только инициализатор для первого члена объединения.   -  person myaut    schedule 21.03.2015


Ответы (1)


Действительно, расширенные списки инициализации недоступны до C++11.

Пока вы помните, что только ОДИН член союза может быть активен в любой момент, вы можете легко решить проблему с помощью конструктора по умолчанию:

template <typename T> class RedBlackNode{
protected:
    union RedBlackPointer{
        RedBlackPointer() : node(0) { }  // <==== default constructor
        RedBlackNode *node;
        struct{
            unsigned value:1;   // for color / other info
        }flag;
    }left, right, parent;
    T key;
public:
    void initialize(T key, RedBlackPointer left = RedBlackPointer(), //refer to default ctor
            RedBlackPointer right = RedBlackPointer(),
            RedBlackPointer parent = RedBlackPointer()){
        this->key = key;
        this->left = left; this->right = right;
        this->parent = parent;
    }
    void show() {
        cout<<left.node<<","<<right.node<<","<<parent.node<<","<<key<<endl;
    }
};   //  <=== ; 

А вот как продемонстрировать, что это работает:

 RedBlackNode<int> N; 
 N.initialize(5); 
 N.show();

Здесь демонстрация и здесь с компилятором, который отверг ваш первоначальный код.

Дополнительный комментарий:

Одна вещь меня озадачивает: в вашем союзе вы объединяете указатель с однобитным флагом.

Это не шокирует само по себе: можно представить, что это уловка, позволяющая избежать накладных расходов на выделение указателя, когда иногда указываемое значение достаточно мало, чтобы хранить его непосредственно в дереве.

Однако в этом случае неясно, как вы узнаете, какой элемент является активным (т.е. когда использовать указатель, а когда использовать флаг).

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

person Christophe    schedule 21.03.2015