adrianmcmenamin
adrianmcmenamin

Reputation: 1129

C++ templates' need for an empty constructor

I am puzzled as to why this is needed or if I have got something else wrong which is causing my problem.

I have some template based code...

template <typename T>
     class redblacknode{

private:
    T value;    
public:
    int colour;
    redblacknode* up;
    redblacknode* left;
    redblacknode* right;
    redblacknode(T& v);
    redblacknode(redblacknode* node);
    redblacknode(redblacknode& node);
    redblacknode* grandparent() const;
    redblacknode* uncle() const;
    redblacknode* sibling() const;
    T& getvalue();
    bool bothchildrenblack() const;
    bool equals(redblacknode*) const;
    bool lessthan(redblacknode*) const;
    void assign(redblacknode*);
    void showinorder(redblacknode*) const;
    void showpreorder(redblacknode*) const;
    void showpostorder(redblacknode*) const;
};

The puzzling thing is that if I declare a class I want to use in this like this...

class pagechain{

....
pagechain(long page);
....

};

pagechain::pagechain(long page)
{
  pagenumber = page;
}

....

pagechain dummy = pagechain(initialvalue);
redblacknode<pagechain>(dummy);

This code fails - saying I need to explicitly initialise T

./redblack.hpp:31:3: error: constructor for 'redblacknode<pagechain>' must explicitly initialize the member 'value' which does not have a default constructor
            redblacknode(T& v);

But I add a dumb constructor to pagechain...

pagechain(){};

The code compiles... what causes this behaviour/what have I got wrong?

Upvotes: 0

Views: 723

Answers (2)

Doc Brown
Doc Brown

Reputation: 20044

The compiler tells you to explicitly initialize value (not T), read the error message exactly.

If you declare a member variable

 T value;

the compiler wants to generate initialization code for the variable "value" as part of any constructor of redblacknode. This works automatically when T has a ctor without parameters. If there is no such ctor (and when do don't provide one, there is none for pagechain, since you have added a ctor with a parameter, which disables the auto generated parameterless ctor), you can instead provide an explicit initialization like

public redblacknode::redblacknode(T& v)
  :value(0)
{
}

(you have to implement all redblacknode constructors that way).

Upvotes: 2

bstamour
bstamour

Reputation: 7766

Though I can't see the code for your constructor redblacknode(T& v), I'm guessing it looks something like the following:

template <typename T> redblacknode<T>::redblacknode(T& v) {
    value = v;
}

What this is doing is calling T's default constructor, then assigning it the value of v. What you want to do instead is to use an initializer statement:

template <typename T> redblacknode<T>::redblacknode(T& v) 
    : value(v)
{
}

This way you don't need to default-construct value, as value is now constructed in one step, instead of two.

Upvotes: 2

Related Questions