0

I have a templated class that needs a specialized constructor when the template parameters is the same type as the class. The code below won't compile.

What's the correct syntax for specifying the use of a particular constructor when the type is of Dual ? In particular, I need to initialize the member 'real' on the initializer list when the template parameter is of type Dual, but not when it isn't (type double for example).

template<class X> class Dual {
 public:
  X real;
  size_t N;
  std::vector<X> imag;//don't know N at compile time


  Dual(size_t _N);

};

template <class X>
inline Dual<X>::Dual(size_t _N):  N(_N), imag(N, 0.0)  {}

template <class X>
inline Dual<Dual<X> >::Dual(size_t _N): real(_N), N(_N), imag(_N, 0.0) {}
//syntax error:  
//error: cpptest.cpp:20:24: error: C++ requires a type specifier for all declarations
//inline Dual<Dual<X> >::Dual(size_t _N): real(_N), N(_N), imag(_N, 0.0) {}
//~~~~~~ 



int main(){

  Dual <double> a(5);
  Dual< Dual < double>> b(5);

}
Ben Jones
  • 919
  • 1
  • 8
  • 22
  • Related but not direct cause: You have no default constructor. How do you deal with the default construction of a type with no default constructor, as you do in your nested declaration? – Mike Bailey Jun 25 '12 at 19:48
  • That's the problem I'm trying to solve with specialization. The type X is either a Dual which requires calling the 1 argument constructor, or its of some floating point type, in which case it doesn't (value is assigned later). – Ben Jones Jun 25 '12 at 19:51
  • It should be obvious then: Add a default constructor to your `Dual` class. – Mike Bailey Jun 25 '12 at 19:52
  • The default constructor with template parameter Dual would leave the object half initialized (the parameter gives the size of the contained vector). – Ben Jones Jun 25 '12 at 19:57

2 Answers2

1

You could provide your constructor with an optional second parameter to initialize real.

template<class X> class Dual {
public:
  X real;
  size_t N;
  std::vector<X> imag;
  Dual(size_t _N, X x = X());
};

template <class X>
inline Dual<X>::Dual(size_t _N, X x):  real(x), N(_N), imag(N, 0.0)  {}

Now, when you have your special Dual, you can initialize it the way you want, by passing in a "prototype".

Dual<double> a(5);
Dual< Dual<double> > b(5, a);

The advantage is that you only have to declare one template. However, if you create a specialization for Dual< Dual<X> >, then you can define the constructor like you had tried (except the imag initialization was wrong, and corrected below).

// Specialize Dual<T> in the case T is a Dual<X>
template <class X> class Dual< Dual<X> > {
public:
    Dual<X> real;
    size_t N;
    std::vector< Dual<X> > imag;
    Dual(size_t _N);
};

template <class X>
inline Dual< Dual<X> >::Dual(size_t _N)
    : real(_N), N(_N), imag(N, Dual<X>(_N)) {}
jxh
  • 69,070
  • 8
  • 110
  • 193
0

You cannot provide a partial specialization of a non-type template, which includes your constructor.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Can you elaborate on why the constructor is a non-type template? – Ben Jones Jun 25 '12 at 20:25
  • @BenJones: Constructors are not types. You can only partially specialize types. You can on the other hand, fully specialize function members of a template, but it must be a full specialization. In your case, you are trying to partially specialize the constructor for `Dual` (for any `X`). – David Rodríguez - dribeas Jun 25 '12 at 20:33