Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Infer template argument from default parameter

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?

like image 690
463035818_is_not_a_number Avatar asked Aug 07 '18 09:08

463035818_is_not_a_number


People also ask

Can template parameters have default arguments?

You cannot give default arguments to the same template parameters in different declarations in the same scope. The compiler will not allow the following example: template<class T = char> class X; template<class T = char> class X { };

Can default argument be used with the template class?

Can default arguments be used with the template class? Explanation: The template class can use default arguments.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)


2 Answers

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. */ }
like image 52
bartop Avatar answered Oct 20 '22 17:10

bartop


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. */ }
like image 2
lubgr Avatar answered Oct 20 '22 17:10

lubgr