30

I tried to write this function with a default template argument:

template<typename A, typename B>
void func(int i1, int i2, A a, B b = 123){
    ...
}

In my mind I can call it like this: func(1, 2, 3) and compiler should deduce type B as int from default value, but I get no instance of overloaded function.
Is it incorrect C++ construction and compiler can't deduce type in this case?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Dave11ar
  • 410
  • 3
  • 8

2 Answers2

46

The type of a template parameter in a function can't be deduced from a default argument. As shown in the example on cppreference.com:

Type template parameter cannot be deduced from the type of a function default argument:

template<typename T> void f(T = 5, T = 7); 

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

However, you can specify a default argument for the template parameter:

template<typename A, typename B = int>
void func(int i1, int i2, A a, B b = 123){
    ...
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 1
    Interestingly, this change also allows deduction with `func(1,2, 3, {});` – Deduplicator Nov 30 '21 at 12:57
  • 2
    @Deduplicator Braced-init-list belongs to non-deduced context, so deduction doesn't occur, the default argument `int` is used instead. Then `{}` is passed as argument, parameter `b` with type `int` is initialized with value `0`. – songyuanyao Nov 30 '21 at 13:12
  • I know, just wanted to add that this invocation works thereafter too. – Deduplicator Nov 30 '21 at 14:43
12

As often when default arguments don't work you can use overloads:

template<typename A, typename B>
void func(int i1, int i2, A a, B b){
    ...
}
template<typename A>
void func(int i1, int i2, A a){
    func(i1,i2,a,123);
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185