3

I have a function which accepts an operator object as an argument. This operator is treated sort of like a callback. The type of this operator object is a template parameter. How can I specify a default parameter for it?

#include <iostream>

template<class IT, class NT>
class A
{
    public:
    class DefaultHandler
    {
    public:
        NT foo() { return NT(); }
    };

    template <class HANDLER>
    void action(HANDLER h = DefaultHandler()) // This default parameter is accepted by the compiler but appears to have no effect
    {
        std::cout << h.foo() << std::endl;
    }
};

int main()
{
    A<int, double> a;
    // I want this to be legal:
    a.action(); // error: no matching function for call to ‘A<int, double>::action()’

    //a.action(A<int, double>::DefaultHandler()); // Works
    return 0;
}
Adam
  • 16,808
  • 7
  • 52
  • 98
  • 1
    Unfortunately, C++03 14.8.2.4/17 says: `A template type-parameter cannot be deduced from the type of a function default argument`. So some workaround like _iammilind_'s answer will be needed. – Ise Wisteria Sep 18 '11 at 03:20
  • @Ise Wisteria, that answers my question exactly, put it in the form of an answer and I'll accept it. – Adam Sep 18 '11 at 18:05
  • @ecatmur How is a question a duplicate of a question that's *a year newer*? – Adam Jun 09 '14 at 16:44
  • @Adam the newer question has a better title and better answers. – ecatmur Jun 09 '14 at 16:49

3 Answers3

3

Having said that default arguments for template are not allowed in current standard. Following is a simple work around to solve your problem:

template <class HANDLER>
void action(HANDLER h) {
    std::cout << h.foo() << std::endl;
}
void action() {  // wrapper
  action(DefaultHandler()); // call the desired funciton
}

Provide a wrapper which makes the effect of default parameter for action(). Demo.

iammilind
  • 68,093
  • 33
  • 169
  • 336
2

Default parameters for template functions are not allowed in C++03 but are allowed in C++11.


References:

C++03 Standard: 14.1.9:

A default template-argument is a template-argument (14.3) specified after = in a template-parameter. Adefault template-argument may be specified for any kind of template-parameter (type, non-type, template).A default template-argument may be specified in a class template declaration or a class template definition. A default template-argument shall not be specified in a function template declaration or a function template definition, nor in the template-parameter-list of the definition of a member of a class template. A default template-argument shall not be specified in a friend template declaration.

C++11: 14.1.9:

A default template-argument is a template-argument (14.3) specified after = in a template-parameter. A de-fault template-argument may be specified for any kind of template-parameter (type, non-type, template) that is not a template parameter pack (14.5.3). A default template-argument may be specified in a template dec-laration. A default template-argument shall not be specified in the template-parameter-lists of the definition of a member of a class template that appears outside of the member’s class. A default template-argument shall not be specified in a friend class template declaration. If a friend function template declaration specifies a default template-argument, that declaration shall be a definition and shall be the only declaration of the function template in the translation unit.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Do you know if they're allowed in C++11? – Adam Sep 17 '11 at 06:17
  • I just saw your edit and that does not seem to apply to my situation. I don't want to specify a default for a template argument, I want to specify a default for a regular argument whose type happens to be templated. Your quote applies to the case where I would like to say `template ` – Adam Sep 17 '11 at 06:27
  • This doesn't answer the question though. The code has a default function template function argument. It is valid in both C++03 and C++11. The question is, why does it not work? – Johannes Schaub - litb Sep 17 '11 at 14:12
0

Unfortunately, C++03 14.8.2.4/17 says:

A template type-parameter cannot be deduced from the type of a function default argument

and provides an example like so:

template <class T> void f(T = 5, T = 7);
void g()
{
    f(1);                   // OK: call f<int>(1,7)
    f();                    // error: cannot deduce T
    f<int>();               // OK: call f<int>(5,7)
}

Because N3290 14.8.2.5/19 states the same specification too, this seems not to change in the new standard...

Ise Wisteria
  • 11,259
  • 2
  • 43
  • 26