C ++ deduction pattern argument

Please consider the code below:

template<typename T> bool function1(T some_var) { return true; } template <typename T> bool (*function2())(T) { return function1<T>; } void function3( bool(*input_function)(char) ) {} 

If i call

 function3(function2<char>()); 

this is normal. But if I call

 function3(function2()); 
Compiler

gives an error that it cannot output an argument for the template.

Could you advise (give an idea) how to rewrite function1 and / or function2 (maybe, in principle, rewrite using classes) to make it normal?

* Added *

I am trying to do something as simple as lambda expressions in Boost.LambdaLib (maybe I'm wrong):

 sort(some_vector.begin(), some_vector.end(), _1 < _2) 

I have done this:

 template<typename T> bool my_func_greater (const T& a, const T& b) { return a > b; } template<typename T> bool my_func_lesser (const T& a, const T& b) { return b > a; } class my_comparing { public: int value; my_comparing(int value) : value(value) {} template <typename T> bool (*operator<(const my_comparing& another) const)(const T&, const T&) { if (this->value == 1 && another.value == 2) { return my_func_greater<T>; } else { return my_func_greater<T>; } } }; const my_comparing& m_1 = my_comparing(1); const my_comparing& m_2 = my_comparing(2); 

Works:

 sort(a, a + 5, m_1.operator< <int>(m_2)); 

But I want it to not require a template argument, as in LambdaLib.

+6
source share
4 answers

Subtraction from the return type is not possible. Therefore, function2 cannot be deduced from what type of return value you expect.

However, the casting operator can be derived. Thus, you can replace function2 with a supporting structure, for example: Unfortunately, there is no standard syntax for declaring a statement operator when specifying an operator without a typedef, and type inference will not work through typedef. After completing the definitions in some compilers (works in g ++ 4.5, does not work in VC ++ 9):

 struct function2 { template <typename T> (*operator bool())(T) { return function1<T>; } }; 

(see also C ++ conversion operator for conversion to a function pointer ).

The call should still look the same.

Note. C ++ 11 introduces an alternative typedef syntax that can be customized by templates. It would be like this:

 struct function2 { template <typename T> using ftype = bool(*)(T); template <typename T> operator ftype<T>() { return function1<T>; } }; 

but I have neither g ++ 4.7 nor VC ++ 10, so I can’t check if it really works.


Added:

The trick in Boost.Lambda is that it does not return functions, but functors. And functors can be class templates. So you will have:

 template<typename T> bool function1(T some_var) { return true; } class function2 { template <typename T> bool operator()(T t) { function1<T>; } }; template <typename F> void function3( F input_function ) { ... input_function(something) ... } 

Now you can write:

 function3(function2); 

and he will solve the pattern inside function3 . All STLs accept functors as templates, so they will work with all STLs.

However, if you do not want to have function3 as a template, there is still a way. Unlike the function pointer, std::function (only for C ++ 11, use boost::function for older compilers), the template can be built from any functor (which includes simple function pointers). Therefore, given the above, you can write:

 void function3(std::function<bool ()(char)> input_function) { ... input_function(something) ... } 

and now you can still call:

 function3(function2()); 

The fact is that std::function has a template constructor that internally generates a template wrapper and stores a pointer to its method, which cannot be called without additional templates.

+5
source

The compiler does not use the expression context to display its template parameters. For the compiler function3(function2()); looks like

 auto tmp = function2(); function3(tmp); 

And he does not know what the function2 template parameter is.

+5
source

After your editing, I think you want to make it easier. See the following type:

 struct Cmp { bool const reverse; Cmp(bool reverse) : reverse(reverse) {} template <typename T> bool operator()(T a, T b) { return reverse != (a < b); } }; 

Now in operator< you return an instance of untyped Cmp depending on the order of your arguments, i.e. m_2 < m_1 will return Cmp(true) and m_1 < m_2 will return Cmp(false) >.

Since there is a templated operator() in place, the compiler will output the correct function inside sort , not your sort call.

+2
source

I am not sure if this will help you, and I am not an expert in this. I watched this post from yesterday, and I want to participate in it.

The template cannot output it because the compiler does not know what type you expect to return. The following is a simple example similar to your function 2 ().

 template<typename T> T foo() { T t; return t; }; 

call this function

 foo(); // no type specified. T cannot be deduced. 

Is it possible to move the template declaration to the class level as follows:

 template<typename T> bool my_func_greater (const T& a, const T& b) { return a > b; } template<typename T> bool my_func_lesser (const T& a, const T& b) { return b > a; } template <typename T> class my_comparing { public: int value; my_comparing(int value) : value(value) {} bool (*operator<(const my_comparing& another) const)(const T&, const T&) { if (this->value == 1 && another.value == 2) { return my_func_greater<T>; } else { return my_func_greater<T>; } } }; 

and declare m_1 and m_2 as shown below:

 const my_comparing<int>& m_1 = my_comparing<int>(1); const my_comparing<int>& m_2 = my_comparing<int>(2); 

Now you can compare the following:

 if( m_1 < m_2 ) cout << "m_1 is less than m_2" << endl; else cout << "m_1 is greater than m_2" << endl; 

I know this is simple, and everyone knows that. Since no one posted this, I want to try.

+1
source

Source: https://habr.com/ru/post/903748/


All Articles