DarkoNaito_09
DarkoNaito_09

Reputation: 101

Constructor Specialization with Templates

#include <iostream>

using namespace std;

template <class T>
struct MyType
{
    public:

    T cont;

    MyType(T value) : cont(value) {}
    MyType(int value = 1) : cont(value) {}
    MyType(double value = 1.2) : cont(value) {}
};

int main()
{
    MyType <int> a;

    return 0;
}

This code gives these errors:

error: 'MyType::MyType(int) [with T = int]' cannot be overloaded

error: with 'MyType::MyType(T) [with T = int]'

Now, how can I specialize some constructor giving them default parameters?

EDIT:

I need a way to do it without copy-pasting all the class for every specialization.

Upvotes: 1

Views: 631

Answers (2)

Jarod42
Jarod42

Reputation: 217245

Simpler would probably be specialization:

template <class T>
struct MyType
{
public:
    T cont;

    MyType(T value) : cont(value) {}
};

template <>
struct MyType<int>
{
public:
    int cont;

    MyType(int value = 1) : cont(value) {}
};

template <>
struct MyType<double>
{
public:
    double cont;

    MyType(double value = 1.1) : cont(value) {}
};

Or, as it seems it is only default value your are interested in, you might tag dispatching default value:

template <typename T> struct tag{};

template <typename T> const T defaultValue(tag<T>) { return {}; }
inline int defaultValue(tag<int>) { return 1;}
inline double defaultValue(tag<double>) { return 1.1;}

template <class T>
struct MyType
{
public:
    T cont;

    MyType(T value = defaultValue(tag<T>)) : cont(value) {}
};

Upvotes: 2

bruno
bruno

Reputation: 32586

Doing

template <class T>
struct MyType
{
    public:

    T cont;

    MyType(T value) : cont(value) {}
    MyType(int value = 1) : cont(value) {}
    MyType(double value = 1.2) : cont(value) {}
};

int main()
{
    MyType <int> a;

    return 0;
}

you have two identical constructors MyType(int value = 1) and MyType(T/*int*/ value), you cannot have that overloading


I need a way to do it without copy-pasting all the class for every specialization.

You can have

#include <iostream>

using namespace std;

template <class T>
struct MyType
{
  public:
    T cont;

    MyType(T value = 1) : cont(value) {}
};

template<>
MyType<int>::MyType(int value) : cont(value + 1) {}

template<>
MyType<double>::MyType(double value) : cont(value + 2) {}

int main()
{
  MyType <int> a;
  MyType <int> aa(10);
  MyType <double> b;

  cout << a.cont << '/' << aa.cont << '/' << b.cont << endl;

  return 0;
}

but you cannot specify an other default value for the parameter of the specialization (error: default argument specified in explicit specialization [-fpermissive]) because as usual the default value is specified in the declaration and not in the definition

Compilation and execution

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall t.cc
pi@raspberrypi:/tmp $ ./a.out
2/11/3

Upvotes: 2

Related Questions