I want to make for_each function for 2D-vector but there is an error:
error: no matching function for call to ‘each(std::vector<std::vector<int> >&, main()::<lambda(int&)>)’
How can I fix it?
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
template <class VarType>
void each(vector<vector<VarType>> &ve, function<void (VarType &)> action) {
for(vector<VarType> &v : ve) {
for(VarType &p : v) {
action(p);
}
}
}
int main() {
vector<vector<int>> map(5);
for(vector<int> &ve : map) {
ve.resize(4);
}
each(map, [](int &val) {
val = 1;
});
}
There are a few solutions. I would recommend to just go for a separate template parameter for the function:
template <class VarType, class Function>
void each(vector<vector<VarType>> &ve, Function action) {
// no more worries
}
The problem is that the compiler cannot figure out the VarType in function<void (VarType&)> from the passed lambda. So doing:
function<void(int&)> action = [](int &val) {
val = 1;
};
each(map, action);
would also work, since this way the type (int&) is already known.
P.S. In C++17 you can do std::function action = [](int &val) { val = 1; };.
While I think taking the function as another template parameter as suggested by #DeiDei is the better solution, here is an alternative:
If you want VarType to be deduced from the first function parameter, then you can make the second parameter a non-deduced context:
template <class VarType>
void each(vector<vector<VarType>> &ve,
typename type_identity<function<void (VarType &)>>::type action) {
for(vector<VarType> &v : ve) {
for(VarType &p : v) {
action(p);
}
}
}
This requires C++20 for std::type_identity and #include<type_traits>, but you can implement your own type_identity easily:
template<typename T>
struct type_identity {
using type = T;
};
This works because everything left to the scope resolution operator :: is a non-deduced context, meaning that the template parameters in it will not be deduced from this function parameter. Your original function fails template argument deduction, because VarType cannot be deduced from the second parameter as the second function argument given in the call does not actually have type std::function<...>.
Related
So I'm trying to do something like the following
int x = 123;
myFunction(x, [](auto y) {
std::cout << y;
});
And myFunction is defined as
template <typename T>
void myFunction(T val, void(*callback)(T)) {
callback(val);
}
When trying to compile the code clang gives me the error could not match 'void (*)(T)' against '(lambda at ...)'. I've figured out this is because you can't deduce the type from a lambda.
So that's actually alright because what I actually want is the parameter type of the callback to be the type deduced from the val parameter of myFunction.
So my question put simply is, is it possible somehow to exclude the callback parameter from being deduced and instead just use the deduced type of val?
is it possible somehow to exclude the callback parameter from being deduced and instead just use the deduced type of val?
Sure.
If you define something like this
template <typename T>
struct self
{ using type = T; };
you can define myFunction() as follows
template <typename T>
void myFunction(T val, void(*callback)(typename self<T>::type)) {
callback(val);
}
Now T is deduced from val and used for callback.
Starting from C++20, you can avoid the self definition and use the newly introduced std::type_identity_t
template <typename T>
void myFunction(T val, void(*callback)(std::type_identity_t<T>)) {
callback(val);
}
One option (and there are a few) is to pass the callable item as a template argument and allow templating to take care of some of the details for you - eg:
template <typename T, typename FUNCTOR>
void myFunction(T val, FUNCTOR callback) {
callback(val);
}
// Note: could be a const ref:
//void myFunction(T val, const FUNCTOR &callback) {
int main()
{
int some_int{1};
myFunction(some_int, [](auto y){ std::cout << y << std::endl; });
float some_float{1.1f};
myFunction(some_float, [](auto y){ std::cout << y << std::endl; });
return 0;
}
Full example here (following your code - but this could be further tidied): https://godbolt.org/z/qr7T5GPd6
This is my code:
#include<iostream>
struct Item {
int val;
};
struct XItem {
int val;
};
void transform(const Item &i, XItem &target) {
target.val = i.val;
}
template<typename T>
void show(const T &v) {
std::cout << v.val << std::endl;
}
template<typename ParamsType, typename ResultType>
void handleRequest(Item &cur, ResultType (*impl)(const ParamsType &p)) {
ParamsType p{};
transform(cur, p);
ResultType res = (*impl)(p);
show(res);
}
struct ResItem {
int val;
};
int main(int argc, char *argv[]) {
Item i{42};
handleRequest(i, [](const XItem &x) {
return ResItem{x.val};
});
return 0;
}
Compiling it gives the following error:
test.cpp:33:3: error: no matching function for call to 'handleRequest'
handleRequest(i, [](const XItem &x) {
^~~~~~~~~~~~~
test.cpp:21:6: note: candidate template ignored: could not match 'ResultType
(*)(const ParamsType &)' against '(lambda at test.cpp:33:20)'
void handleRequest(Item &cur, ResultType (*impl)(const ParamsType &p)) {
^
I am unsure why this happens, however I do suspect that because the lambda, while being implicitly convertible to a function pointer, isn't one, the template parameters can't be deduced from it.
I tried using std::function<ResultType(const ParamsType &p)> instead, which also doesn't work. This question details the problem, so I tried to use its solution:
template<typename ParamsType, typename ResultType, typename Callback>
void handleRequest(Item &cur, Callback cb) {
ParamsType p = transform(cur);
ResultType res = std::invoke(cb, p);
show(res);
}
However, now ParamsType and ResultType cannot be implicitly deduced from the callback, I would need to give them explicitly. But I really want to infer ResultType because in the actual code, it can be quite lengthy (it is inferred from the lambda return statement, which is more complex than in this minimal example). I need the two types because both transform and show are overloaded and need the types to bind.
Is it possible to have handleRequest infer those types in this scenario and if so, how?
The problem is, implicit conversion (from lambda to function pointer) is not considered in template argument deduction, which fails deducing the template parameters.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
You can specify the template arguments explicitly to bypass the deduction,
handleRequest<XItem, ResItem>(i, [](const XItem &x) {
return ResItem{x.val};
});
Or convert the lambda to function pointer explicitly,
handleRequest(i, static_cast<RestItem(*)(const XItem&)>([](const XItem &x) {
return ResItem{x.val};
}));
Or use the operator+ to convert the lambda to function pointer.
handleRequest(i, +[](const XItem &x) {
return ResItem{x.val};
});
I'm trying to catch up on C++11 and all the great new features. I'm a bit stuck on lambdas.
Here's the code I was able to get to work:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>
using namespace std;
template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
What I would like to have is this:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Basically I want to narrow down the possible lambdas to a sensible subset of functions.
What am I missing? Is this even possible? I'm using GCC/G++ 4.6.
Stephan T. Lavavej explains why this doesn't work in this video. Basically, the problem is that the compiler tries to deduce BaseT from both the std::vector and the std::function parameter. A lambda in C++ is not of type std::function, it's an unnamed, unique non-union type that is convertible to a function pointer if it doesn't have a capture list (empty []). On the other hand, a std::function object can be created from any possible type of callable entity (function pointers, member function pointers, function objects).
Note that I personally don't understand why you would want to limit the incoming functors to that specific signature (in addition to the fact that indirection through a polymorphic function wrapper, like std::function, is by far more inefficient than a direct call to a functor (which may even be inlined)), but here's a working version. Basically, it disables argument deduction on the std::function part, and only deduces BaseT from the std::vector argument:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Live example on Ideone.
Another possible way would be to not restrict the functor type directly, but indirectly through SFINAE:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Live example on Ideone.
This function will be removed from the overload set if fun doesn't take an argument of type T& or if the return type is not convertible to bool. The , void() makes f's return type void.
As has been revealed by other posters, this is a template argument deduction for std::function.
One intuitive way to make the second code snippet work is to add your base type when calling the template function: findMatches<int>.
Another way not mentioned by Xeo is using std::is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
It avoids wrapping lamda into std::function, and provides a cleaner error message.
Somebody can help me to build this source code in a right way,
I understand that I shold declare the callBack as std::function<void(std::unique_ptr<int>&& param)> because this take a no copy
constructible param(std::unique_ptr), so what is the correct type if I no use auto to deduce the type?
#include <functional>
#include <memory>
template <class T>
class SomeClass {
void someFunctionCallback(float o) = 0;
};
template <>
class SomeClass<float> {
public:
SomeClass() = default;
inline void someFunction() {
// std::function<void()>
auto callBack {
std::move(std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::unique_ptr<int>{new int(9)}))};
useCallBack(std::move(callBack));
}
inline void someFunctionCallback(std::unique_ptr<int>&& param) {
}
inline void useCallBack(std::function<void()> &&callBack) {
// callBack();
}
};
int main() {
SomeClass<float> k;
k.someFunction();
return 0;
}
Your code has a couple of problems. First, auto { ... } will deduce an std::initializer_list. That's not what you want. Use a brace-or-equal initializer instead.
auto callBack =
std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::unique_ptr<int>{new int(9)});
Second, your function takes an rvalue-reference, but std::bind will pass an lvalue. Read Passing rvalues through std::bind for a full explanation, but as a workaround you can use this ugly cast:
using uptr = std::unique_ptr<int>;
auto callBack =
std::bind(&SomeClass<float>::someFunctionCallback,
this,
std::bind(static_cast<uptr&&(&)(uptr&)>(std::move<uptr&>),
std::unique_ptr<int>{new int(9)})
) ;
Finally, just make your function a template. The whole idea is not to worry about the type, and auto follows the rules of template argument deduction anyway.
template <typename T>
inline void useCallBack(T callBack) {
callBack();
}
I'm trying to catch up on C++11 and all the great new features. I'm a bit stuck on lambdas.
Here's the code I was able to get to work:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <string>
#include <functional>
using namespace std;
template<typename BaseT, typename Func>
vector<BaseT> findMatches(vector<BaseT> search, Func func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
void Lambdas()
{
vector<int> testv = { 1, 2, 3, 4, 5, 6, 7 };
auto result = findMatches(testv, [] (const int &x) { return x % 2 == 0; });
for(auto i : result)
{
cout << i << endl;
}
}
int main(int argc, char* argv[])
{
Lambdas();
return EXIT_SUCCESS;
}
What I would like to have is this:
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Basically I want to narrow down the possible lambdas to a sensible subset of functions.
What am I missing? Is this even possible? I'm using GCC/G++ 4.6.
Stephan T. Lavavej explains why this doesn't work in this video. Basically, the problem is that the compiler tries to deduce BaseT from both the std::vector and the std::function parameter. A lambda in C++ is not of type std::function, it's an unnamed, unique non-union type that is convertible to a function pointer if it doesn't have a capture list (empty []). On the other hand, a std::function object can be created from any possible type of callable entity (function pointers, member function pointers, function objects).
Note that I personally don't understand why you would want to limit the incoming functors to that specific signature (in addition to the fact that indirection through a polymorphic function wrapper, like std::function, is by far more inefficient than a direct call to a functor (which may even be inlined)), but here's a working version. Basically, it disables argument deduction on the std::function part, and only deduces BaseT from the std::vector argument:
template<class T>
struct Identity{
typedef T type;
};
template<typename BaseT>
vector<BaseT> findMatches(vector<BaseT> search,
typename Identity<function<bool (const BaseT &)>>::type func)
{
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
Live example on Ideone.
Another possible way would be to not restrict the functor type directly, but indirectly through SFINAE:
template<class T, class F>
auto f(std::vector<T> v, F fun)
-> decltype(bool(fun(v[0])), void())
{
// ...
}
Live example on Ideone.
This function will be removed from the overload set if fun doesn't take an argument of type T& or if the return type is not convertible to bool. The , void() makes f's return type void.
As has been revealed by other posters, this is a template argument deduction for std::function.
One intuitive way to make the second code snippet work is to add your base type when calling the template function: findMatches<int>.
Another way not mentioned by Xeo is using std::is_convertible:
template<typename BaseT, typename FUNC>
vector<BaseT> findMatches(vector<BaseT> search, function <bool (const BaseT &)> func)
{
static_assert(std::is_convertible<FUNC, function<bool (const BaseT &)> >::value, "func must be convertible to ...");
vector<BaseT> tmp;
for(auto item : search)
{
if( func(item) )
{
tmp.push_back(item);
}
}
return tmp;
}
It avoids wrapping lamda into std::function, and provides a cleaner error message.