Infer template argument from default parameter
Asked Answered
K

2

7

Consider this code:

#include <functional>

template <typename T,typename COMP>
bool foo(T a,T b,COMP c = std::less<T>()) { 
    return c(a,b); 
}

bool bar(int a, int b){ return a<b;}

int main(){
    foo(1,2,bar);               // OK
    foo(1,2,std::less<int>());  // OK
    foo(1,2);                   // error
}

The first two calls are fine, but it seems to be forbidden to let the compiler infer the type of COMP from the default parameter:

<source>:14:5: error: no matching function for call to 'foo'    
    foo(1,2);    
    ^~~    
<source>:4:6: note: candidate template ignored: couldn't infer template argument 'COMP'    
bool foo(T a,T b,COMP c = std::less<T>()) {    
     ^   
1 error generated.    
Compiler returned: 1

Am I missing something? I dont really understand why the compiler "couldn't infer template argument 'COMP'" and I rather suspect that it is not allowed to do so.

Is it possible to infer the template argument from a default parameter? If not, why?

Klump answered 7/8, 2018 at 9:43 Comment(0)
D
11

I'd suggest doing it the way it is done in standard C++ containers like map or set. It allows to infer the type and also allows to use default argument:

template <typename T,typename COMP = std::less<T>>
bool foo(T a,T b, COMP c = COMP()) { /* As before. */ }
Dynah answered 7/8, 2018 at 9:51 Comment(2)
@LuisMachuca How would you want it to work with >> operator?Dynah
Point, I was somehow thinking of a class definition.Jubbah
D
2

It is not possible to infer the type. You can manually specify a default type, too:

template <typename T,typename COMP = std::less<T>>
bool foo(T a,T b,COMP c = std::less<T>()) { /* As before. */ }
Dimenhydrinate answered 7/8, 2018 at 9:47 Comment(3)
should be std::less<T>, no?Klump
std::less<> is unavailable in C++98.Twopiece
Right, I ignored the tag... thanks for the hint, I'll fix it.Dimenhydrinate

© 2022 - 2024 — McMap. All rights reserved.