LI.LE
LI.LE

Reputation: 107

Default argument with template in C++

I'm designing an interface, by which users can define a class that tells what they want to do.
The code is something like the following,

#include <stdio.h>

class Dummy{
public:
    void do(){ printf("do nothing\n"); }
};

class Task{
public:
    void do(){ printf("do something\n"); }
};

template <class TASK>
void func(TASK &task = Dummy()){
    task.do();
}

int main(){
    func(); // do nothing
    Task task;
    func(task); // do something
}

How to make it work?

Upvotes: 1

Views: 144

Answers (2)

Peter
Peter

Reputation: 36617

For starters, don't have an identifier (function named) named do, since do is a language keyword. Using it as an identifier is a diagnosable error. There's no option other than changing the name of the function.

Second, the argument will of func() will need to be const, since the default value being passed is a temporary (which can only be bound to a const reference). This also means your function in the classes needs to be const qualified.

Third, when calling func() it is necessary to either pass SOME information so the compiler can work out how to instantiate the template. If you want to pass no information at all at the call site (i.e. func()) then you need to have a non-templated overload.

Fourth, use C++ streams rather than C I/O.

 class Dummy
 {
    public:
       void do_it() const { std::cout << "do nothing\n"; }
 };

 class Task
 {
    public:
       void do_it() const { std::cout << "do something\n"; }
 };

 template <class TASK>
  void func(const TASK &task)
  {
     task.do_it();
  }

  void func()
  {
      func(Dummy());
  }

  int main()
  {
     func(); // do nothing
     Task task;
     func(task); // do something
  }

Option 2 is to replace the two versions of func() above with

 template <class TASK = Dummy>
  void func(const TASK &task = TASK())
  {
     task.do_it();
  }

Upvotes: 1

Afshin
Afshin

Reputation: 9173

The main issue is this func argument:

TASK &task = Dummy()

It will not work unless it is const. This happens because non-const lvalue reference to type cannot bind to a temporary.

But if you can use const there, you can easily solve your problem:

class Dummy{
public:
    void doit() const { printf("do nothing\n"); }
};

class Task{
public:
    void doit() const { printf("do something\n"); }
};

template <class TASK = Dummy>
void func(const TASK &task = TASK()){
    task.doit();
}

int main(){
    func(); // do nothing
    Task task;
    func(task); // do something
}

Upvotes: 1

Related Questions