When working with std::priority_queue, I tried to clear the contents of the priority queue like this:
#include <iostream>
#include <queue>
#include <vector>
using std::cout;
using std::priority_queue;
using std::vector;
int main() {
const auto comp = [](int a, int b) {
return a > b;
};
auto a = priority_queue<int, vector<int>, decltype(comp)>(comp);
a.push(10);
a.push(9);
a.push(8);
// 3
cout << a.size() << '\n';
a = priority_queue<int, vector<int>, decltype(comp)>(comp);
// 0
cout << a.size() << '\n';
return 0;
}
When compiling with Clang, I got an error:
In file included from tmp.cpp:1:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1/queue:455:39: error: no viable overloaded '='
{c = _VSTD::move(__q.c); comp = _VSTD::move(__q.comp); return *this;}
~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~
tmp.cpp:19:7: note: in instantiation of member function 'std::priority_queue<int, std::vector<int>, const (lambda at tmp.cpp:9:23)>::operator=' requested here
a = priority_queue<int, vector<int>, decltype(comp)>(comp);
^
tmp.cpp:9:23: note: candidate function (the implicit copy assignment operator) not viable: 'this' argument has type 'std::priority_queue<int, std::vector<int>, const (lambda at tmp.cpp:9:23)>::value_compare' (aka 'const (lambda at tmp.cpp:9:23)'), but method is not marked const
const auto comp = [](int a, int b) {
^
1 error generated.
Why would this give me an error? And is there any way to fix it? Thanks.
decltype(comp) is a const type, const auto comp, that makes the priority_queue member variable storing comp to be constant, thus can't be re-assigned.
You might want
priority_queue<int, vector<int>, remove_cv_t<decltype(comp)>>(comp);
Or
auto comp = [](int a, int b) {
return a > b;
};
The copy assignment operator for lambdas are implicitly deleted. The fix:
std::function<bool(int, int)> comp = [](int a, int b) {
return a > b;
};
Related
Can't figure out why std::ranges::equal in the code below does not compile:
struct A { int x; };
using Map = std::map<int, A>;
void some_func()
{
std::vector<A> v{ {0}, {1}, {2}, {3} };
auto v2m = [](const A& a) { return std::pair<int, A>(a.x, a); };
const auto actual = std::ranges::single_view(v[2]) | std::views::transform(v2m);
Map expected{ {v[2].x, v[2]} };
//Does not compile.
bool equals = std::ranges::equal(actual, expected);
}
The compiler errors with MSVC are:
error C2672: 'operator __surrogate_func': no matching overloaded function found
error C7602: 'std::ranges::_Equal_fn::operator ()': the associated constraints are not satisfied
Problem 1: A isn't comparable, so you cannot compare it using std::ranges::equal with the default predicate. Solution:
struct A {
int x;
friend auto operator<=>(const A&, const A&) = default;
};
Problem 2: Your transform function produces std::pair<int, A> which doesn't match with the elements of map which are std::pair<const int, A>. Solution: use std::pair<const int, A> (or just Map::value_type so that there's less room for mistakes).
I'm using a template function, which the goal is reciever a vector and a function, and return the function type.
template <typename T, typename Function>
auto apply(const std::vector<T>& V, const Function &F){
vector<Function> x; # ERROR HERE
return x;
}
But the IDE give me error (http://coliru.stacked-crooked.com/a/ee6ce2127e013a18):
/usr/local/include/c++/10.2.0/ext/new_allocator.h: In instantiation of 'class __gnu_cxx::new_allocator<double(double)>':
/usr/local/include/c++/10.2.0/bits/allocator.h:116:11: required from 'class std::allocator<double(double)>'
/usr/local/include/c++/10.2.0/bits/stl_vector.h:87:21: required from 'struct std::_Vector_base<double(double), std::allocator<double(double)> >'
/usr/local/include/c++/10.2.0/bits/stl_vector.h:389:11: required from 'class std::vector<double(double), std::allocator<double(double)> >'
main.cpp:10:22: required from 'auto apply(const std::vector<T>&, const Function&) [with T = int; Function = double(double)]'
main.cpp:19:39: required from here
/usr/local/include/c++/10.2.0/ext/new_allocator.h:96:7: error: 'const _Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::const_reference) const [with _Tp = double(double); __gnu_cxx::new_allocator<_Tp>::const_pointer = double (*)(double); __gnu_cxx::new_allocator<_Tp>::const_reference = double (&)(double)]' cannot be overloaded with '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = double(double); __gnu_cxx::new_allocator<_Tp>::pointer = double (*)(double); __gnu_cxx::new_allocator<_Tp>::reference = double (&)(double)]'
96 | address(const_reference __x) const _GLIBCXX_NOEXCEPT
| ^~~~~~~
/usr/local/include/c++/10.2.0/ext/new_allocator.h:92:7: note: previous declaration '_Tp* __gnu_cxx::new_allocator<_Tp>::address(__gnu_cxx::new_allocator<_Tp>::reference) const [with _Tp = double(double); __gnu_cxx::new_allocator<_Tp>::pointer = double (*)(double); __gnu_cxx::new_allocator<_Tp>::reference = double (&)(double)]'
92 | address(reference __x) const _GLIBCXX_NOEXCEPT
| ^~~~~~~
main.cpp: In function 'int main(int, char**)':
main.cpp:19:31: error: conversion from 'vector<double(double),allocator<double(double)>>' to non-scalar type 'vector<double,allocator<double>>' requested
19 | vector<double> r = ::apply(v, seno);
| ~~~~~~~^~~~~~~~~
This is call of the main function.
double seno( double n ) { return sin(n); }
int main( int argc, char* argv[]) {
vector<int> v{ 1, 2, 3, 4, 5 };
vector<double> r = ::apply(v, seno);
cout << r;
return 0;
}
I don't know what I'm doing wrong, so How can I improve this method and pass trough this error?
EDIT: The purpse to generalize the in method insted of using double in the vector is because I want o re-use in another way. So I've generalize the most that I can.
vector<Function> x; // ERROR HERE defines a vector of function pointers. But that's not what you want - you want a vector of the return type of the function. And that's what decltype() is for.
In your apply function, F is the function to be called and T is the type of the values in the vector being passed in. That means T() is the default value of the items in the vector (in this case the default value of int is 0). Then, F(T()) would actually call the function with 0 and return something so decltype(F(T())) tells you the type of the thing returned.
That means you need to write vector<decltype(F(T()))> x; instead.
T() works because the type is int and it is default constructible. As #alterigel said in the comments std::declval<T>() is better when the type is not default constructible.
So vector<decltype(F(std::declval<T>()))> x; might be needed in some situations.
The whole program would look like:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
template <typename T, typename Function>
auto apply(const std::vector<T>& V, const Function &F) {
vector<decltype(F(T()))> x;
for(auto a : V)
x.push_back(F(a));
return x;
}
double seno( double n ) { return sin(n); }
int main( int argc, char* argv[]) {
vector<int> v{ 1, 2, 3, 4, 5 };
vector<double> r = ::apply(v, seno);
for (auto a : r)
cout << a << " ";
return 0;
}
Try it here: https://onlinegdb.com/SknTsVaHO
I'm trying to map string to function pointer, so that I can call the function with iter->second(arg) instead of if-else.
I have written a simple one without class, and it works as expected.
But when I modify it as below, it shows compile errors.
#include <functional>
#include <iostream>
#include <unordered_map>
#include <string>
using std::string;
class A{
private:
int a(int num, string s) { return s.size() + num; }
int b(int num, string s) { return num - s.size(); }
public:
void ido(string str){
typedef std::function<int(int, string)> process_func;
std::unordered_map<string, process_func> m;
m.insert(std::make_pair<string, process_func>("a", &A::a));
// using std::placeholders::_1;
// m.insert(std::make_pair<string, process_func>("a", std::bind(&A::a, this, _1)));
// m["a"] = std::bind(&A::a, this, _1);
// m.insert({{"a", &A::a}, {"b", &A::b}});
auto x = m.find(str);
if(x == m.end()) {
std::cout << "Not supported!" << std::endl;
}
std::cout << x->second(10, "hello") << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
a.ido(string(argv[1]));
return 0;
}
The errors are:
function.cc: In member function ‘void A::ido(std::string)’:
function.cc:17:65: error: no matching function for call to ‘make_pair(const char [2], int (A::*)(int, std::string))’
m.insert(std::make_pair<string, process_func>("a", &A::a));
^
function.cc:17:65: note: candidate is:
In file included from /usr/include/c++/4.8.2/utility:70:0,
from /usr/include/c++/4.8.2/tuple:38,
from /usr/include/c++/4.8.2/functional:55,
from function.cc:1:
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template<class _T1, class _T2> constexpr std::pair<typename std::__decay_and_strip<_Tp>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&)
make_pair(_T1&& __x, _T2&& __y)
^
/usr/include/c++/4.8.2/bits/stl_pair.h:276:5: note: template argument deduction/substitution failed:
function.cc:17:65: note: cannot convert ‘&A::a’ (type ‘int (A::*)(int, std::string) {aka int (A::*)(int, std::basic_string<char>)}’) to type ‘std::function<int(int, std::basic_string<char>)>&&’
m.insert(std::make_pair<string, process_func>("a", &A::a));
What does the error mean? How to fix it?
While your functions 'a' and 'b' do not depend on 'this' (they do not access anything inside class A), the compiler is not smart enough to deduce this. So the error means that you are trying to convert 'pointer to method' to 'pointer to function', which is incorrect conversion. 'Pointer to method' requires and object to be called on. You need to declare methods 'a' and 'b' as 'static' to indicate that they are actually standalone functions, not methods of the class.
I have the below code where I am trying to print the multiplication table of 10.
I have bound the function multiply with two parameters 5 and 2. I am passing the bound function to create a lambda. And then I am attempting to pass the lambda to the for_each loop to print the Multiplication Table. I intutively kind of know that I may be pushing it a bit too far. But I don't know the exact reason. Can someone explain.
#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <functional>
#include <future>
#include <array>
#include <unistd.h>
using namespace std;
using namespace std::placeholders;
int multiply(int a, int b, int c)
{
return a*b*c;
}
int main()
{
auto f = std::bind(multiply, 5, 2, _1);
std::function<int(int,int,int)> f1 = [f](int a){cout << "Multiplication Table (10) :" << f(a) << endl; };
vector<int> vec = {1,2,3,4,5,6,7,8,9,10};
for_each(vec.begin(), vec.end(), f1);
return 0;
}
The error that I am getting is shown below.
/home/karthik/Workspace/cpppen/learning/main.cpp: In function ‘int main()’:
/home/karthik/Workspace/cpppen/learning/main.cpp:26:107: error: conversion from ‘main()::<lambda(int)>’ to non-scalar type ‘std::function<int(int, int, int)>’ requested
std::function<int(int,int,int)> f1 = [f](int a){cout << "Multiplication Table (10) :" << f(a) << endl;};
^
In file included from /usr/include/c++/7/algorithm:62:0,
from /home/karthik/Workspace/cpppen/learning/main.cpp:6:
/usr/include/c++/7/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Funct = std::function<int(int, int, int)>]’:
/home/karthik/Workspace/cpppen/learning/main.cpp:30:40: required from here
/usr/include/c++/7/bits/stl_algo.h:3884:5: error: no match for call to ‘(std::function<int(int, int, int)>) (int&)’
__f(*__first);
~~~^~~~~~~~~~
In file included from /usr/include/c++/7/functional:58:0,
from /home/karthik/Workspace/cpppen/learning/main.cpp:8:
/usr/include/c++/7/bits/std_function.h:701:5: note: candidate: _Res std::function<_Res(_ArgTypes ...)>::operator()(_ArgTypes ...) const [with _Res = int; _ArgTypes = {int, int, int}]
function<_Res(_ArgTypes...)>::
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
I am passing a function with two bound and one placeholder parameter.
No you're not. Your lambda looks like this:
[f](int a) {
cout << "Multiplication Table (10) :" << f(a) << endl;
}
That is the callable object that you are passing to std::function. Now, the lambda is callable with only one argument, not three. Notice:
[/*...*/](int a){ /*...*/ }
// ^^^^^
// one parameter
Likewise, f is a callable object with only one parameter. You can't call it with three arguments, because you've bound two parameters to specific values, so, for all intents and purposes, there are no three parameters. Maybe this makes it more clear:
auto add = [](int a, int b) { return a + b; };
auto addTo5 = [&add](int a) { return add(a, 5); };
add(1, 2); // ok, lambda takes two parameters
addTo5(3); // ok, lambda takes one parameter
addTo5(1, 2); // not ok, lambda doesn't take two parameters
std::function<int(int, int)> fadd = add; // ok
std::function<int(int)> faddTo5 = addTo5; // ok
std::function<int(int, int)> faddTo5fail = addTo5; // not ok, same reason
// addTo5 is approximately what std::bind does: It generates an object which has
// several variables "fixed", and so only takes the placeholder arguments that aren't
// specified.
So, the fix is to change f1's type to reflect what you are actually storing; a callable that takes an int and returns nothing:
std::function<void(int)> f1 = /*...*/;
// ^^^^
// lambda returns nothing
This question already has answers here:
Why isn't vector<bool> a STL container?
(6 answers)
Closed 4 years ago.
I have the following code snippet, which takes the std::vector<int> list and writes a zero in all vector elements. This example is working perfectly fine.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<int> list {1, 1, 2};
auto reset = [](int & element){element = 0;};
auto print = [](int element) {std::cout << element << " ";};
std::for_each(list.begin(), list.end(), reset);
std::for_each(list.begin(), list.end(), print);
}
If I take change the type of the vector from int to bool, the code will not compile.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<bool> list {true, true, false};
auto reset = [](bool & element){element = false;};
auto print = [](int element) {std::cout << element << " ";};
std::for_each(list.begin(), list.end(), reset);
std::for_each(list.begin(), list.end(), print);
}
https://godbolt.org/g/2EntgX
I don't understand the compiler error message:
/opt/compiler-explorer/gcc-7.2.0/lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_algo.h:3884:2: error: no matching function for call to object of type '(lambda at
:7:18)'
__f(*__first);
^~~
:10:10: note: in instantiation of function template
specialization 'std::for_each:7:18)>' requested here
std::for_each(list.begin(), list.end(),reset);
^
:7:18: note: candidate function not viable: no known
conversion from 'std::_Bit_iterator::reference' (aka
'std::_Bit_reference') to 'bool &' for 1st argument
auto reset = [](bool & element){element = false;};
^
:7:18: note: conversion candidate of type 'void (*)(bool &)'
Why does std::foreach work with a std::vector<int>, but does not work with a std::vector<bool>?
Is the memory optimisation of an std::vector<bool> (see here ) part of the answer?
Reason
The problem stems from the fact that dereferencing an iterator that came from std::vector<bool> doesn't return bool&, but rather a proxy object. Thus, it is not regarded as stl container (thanks to #KillzoneKid).
Fix
Use auto element in the parameter list. In general, if you don't care about the type, use auto&& in the lambda parameter list.
#include <vector>
#include <iostream>
#include <algorithm>
int main () {
std::vector<bool> list {true, true, false};
auto reset = [](auto && element){element = false;};
auto print = [](int element) {std::cout<< element << " ";};
std::for_each(list.begin(), list.end(),reset);
std::for_each(list.begin(), list.end(),print);
}
Demo.
Trying to use auto& will trigger compilation error again, as the proxy returned is not lvalue, but rvalue. Thus, auto&& has even more benefits than usual.