views:

933

answers:

3

So I have this piece of code and out of convenience I want the default parameter for its constructor be of the int kind and 0. (I have more parameters in a class of my project and one of them is optional and I don't want to write the constructor twice because its big)

class mama{
    public:
    template<typename x> mama(x i=int(0)){}
};

int main(){
    mama x;
}

This doesn't work because it says it can't find the constructor so is there another way I can do this?

error: no matching function for call to ‘mama::mama()'
note: candidates are: mama::mama(const mama&)
+3  A: 

Refactor your constructor into a private initialization function and wrapper constructors, then add a default, like so:

class mama {
  private:
    template<typename x> void init(x i) { /* ... */ }
  public:
    template<typename x> mama(x i) { init(i); }
    mama() { init((int)0); }
};
bdonlan
we ended up with exactly the same code. neat :)
Johannes Schaub - litb
The fact that your ctor is templated is a strong hint for me to templatize the whole class. YMMV!
dirkgently
Probably; I can't imagine how a templated constructor like this would be useful without templatizing the class, but this gives what the original question asked for, and someone else covered making the class a template :)
bdonlan
Actually templatized constructor is very useful. For example boost::shared_ptr, boost::any, and may implementation of handle-body or similar pattern uses this technique.
Shing Yip
+1 this solves the second issue of not having to copy/paste chunks of code to provide multiple similar constructors by refactoring the initialization code into separate method and call it from constructor with required parameters. More flexible to maintain.
stefanB
+3  A: 

Note that default template parameters are not allowed for function templates. Why not create a class template?

template <class T=int>
class mama{
    public:
    mama<T>(T i=0){}
};

int main(){
    mama<> x; // no argument based template parameter deduction possible
}
dirkgently
I thought of the same :)
Devil Jin
A: 

Default value works just like overload, so...

class mama{
public:
    template<typename x> mama(x i){}
    mama(int i = 0) {}
};

When you create mama with no argument, the construct with default int is matched before any templated constructor.

Shing Yip
Yes, but that doesn't avoid the code duplication. Csiz wanted a single constructor.
Ari
If you don't want to write the constructor body twice factor it into a function, like what bdonlan suggested. However, if you later want to specialize mama::mama(int), with bdonlan's solution (having a default constructor with no argument instead of constructor with int and default to 0) you cannot do it without adding another constructor.
Shing Yip