I'm getting these errors. Why?
In file included from /usr/include/c++/4.7/algorithm:63:0,
from prog.cpp:2:
/usr/include/c++/4.7/bits/stl_algo.h: In instantiation of ‘_OIter std::transform(_IIter, _IIter, _OIter, _UnaryOperation) [with _IIter = __gnu_cxx::__normal_iterator >; _OIter = std::back_insert_iterator >; _UnaryOperation = main()::]’:
prog.cpp:10:98: required from here
/usr/include/c++/4.7/bits/stl_algo.h:4951:2: error: no match for call to ‘(main()::) (int&)’
prog.cpp:10:64: note: candidates are:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from prog.cpp:2:
/usr/include/c++/4.7/bits/stl_algo.h:4951:2: note: int (*)(int, int)
/usr/include/c++/4.7/bits/stl_algo.h:4951:2: note: candidate expects 3 arguments, 2 provided
prog.cpp:10:79: note: main()::
prog.cpp:10:79: note: candidate expects 2 arguments, 1 provided
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v {1, 2, 3, 4, 5, 6};
std::vector<int> r;
std::transform(v.begin(), v.end(), std::back_inserter(r), [] (int a, int b) { return a + b; });
}
This code is supposed to add up each pair of numbers and put it into the r vector but it's not working. Why is that?
You've picked the overload of transform() that works on a single range - and thus expects a unary functor to be provided as the last argument.
If what you want is to work on two ranges (perhaps two "copies" of the same range?), then you should do:
std::transform(v.begin(), v.end(), v.begin(),
// ^^^^^^^^^
std::back_inserter(r), [] (int a, int b) { return a + b; });
So here is the full code:
#include <algorithm>
#include <vector>
int main()
{
std::vector<int> v {1, 2, 3, 4, 5, 6};
std::vector<int> r;
std::transform(v.begin(), v.end(), v.begin(),
std::back_inserter(r), [] (int a, int b) { return a + b; });
}
And here is a compiling live example.
However, unless you just wanted to practice with the overload of std::transform() that operates on two input ranges, you could follow Konrad Rudolph's advice from the comments, and write:
std::transform(v.begin(), v.end(),
std::back_inserter(r), [] (int a) { return a * 2; });
If, instead, you want to perform a sum of each pair of consecutive elements and store the result in the r vector while using a transform-like approach, then you may resort to Boost.Range, and write something like:
#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
// ...
namespace rng = boost::adaptors;
// This will fill r with values { 3, 7, 11 }
boost::transform(
v | rng::strided(2),
std::make_pair(v.begin() + 1, v.end()) | rng::strided(2),
std::back_inserter(r),
[] (int a, int b) { return a + b; });
Here is a live example.
Also, as pointed out by NeelBasu in the comments, instead of using std::make_pair() to define the second range, you could write a more expressive (and compact) version based on the sliced range adaptor:
boost::transform(
v | rng::strided(2),
v | rng::sliced(1, v.size()) | rng::strided(2),
std::back_inserter(r),
[] (int a, int b) { return a + b; });
Related
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;
};
Consider the following uncomplicated code:
#include <thread>
#include <utility>
#include <vector>
#include <atomic>
#include <queue>
#include <iostream>
#include <functional>
using namespace std;
template<class It, class Fun>
void parallel_for(size_t num_threads, It first, It end, const Fun& fun) {
std::queue<std::thread> ts;
for (It it = first; it != end; ++it) {
if (std::distance(first, it) % num_threads == 0) {
fun(*it);
} else {
if (ts.size() == num_threads-1) {
ts.front().join();
ts.pop();
}
ts.push(std::thread(fun, std::ref(*it)));
}
}
while (not ts.empty()) {
ts.front().join();
ts.pop();
}
}
int main() {
std::atomic_int counter = 1;
auto lam = [&counter](auto& vl) {
vl = std::pair(counter++, -1);
};
// The following usage of std::ref works okay:
pair<int, int> x;
auto blam = bind(lam, ref(x));
blam();
// Nevertheless, the next line fails:
// lam(ref(x));
// As well as the next two ones:
// vector<pair<int, int>> v = {{4, 2}};
// parallel_for(thread::hardware_concurrency(), begin(v), end(v), lam);
return 0;
}
GCC's error on the last two lines, in particular, is
In file included from ./src/csc_cpp/passing_lambdas.cpp:1:
/usr/include/c++/10/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = const main()::<lambda(auto:1&)>&; _Args = {std::reference_wrapper<std::pair<int, int> >}; <template-parameter-1-3> = void]’:
./src/csc_cpp/passing_lambdas.cpp:22:26: required from ‘void parallel_for(size_t, It, It, const Fun&) [with It = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int> > >; Fun = main()::<lambda(auto:1&)>; size_t = long unsigned int]’
./src/csc_cpp/passing_lambdas.cpp:47:71: required from here
/usr/include/c++/10/thread:136:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
136 | typename decay<_Args>::type...>::value,
| ^~~~~
I am sure this is a trivial matter, but I am anyway struggling to understand this. I think I have been following the available examples on std::thread::thread()'s intended use quite closely, but this does not compile. What am I doing wrong?
First, let me clarify, because I'm not sure if it's obvious: the trick behind std::ref is that it returns an object of type std::reference_wrapper<T>, so you can use the result as object, but the object is implicitly convertible to T&, so it can be substituted where T& is needed.
lam(ref(x)); fails because you use auto in lam. Compiler doesn't know that you want vl to be std::pair<int, int>&, it deduces from what it gets. std::ref returns a temporary of std::reference_wrapper<std::pair<int, int>>, which cannot be bound to non-const reference. Use explicit type in lambda and it compiles:
auto lam = [&counter](std::pair<int, int>& vl) {
vl = std::pair(counter++, -1);
};
lam(std::ref(x));
Alternatively, you can explicitly convert to std::pair<int, int>& using get() or static_cast
auto lam = [&counter](auto& vl) {
vl = std::pair(counter++, -1);
};
lam(std::ref(x).get());
lam(static_cast<std::pair<int, int>&>(std::ref(x)));
The second part with parallel_for has exactly the same issue, you pass rvalue of std::reference_wrapper to lam.
About
lam(ref(x));
x is an lvalue while the ref(x) is a temporary reference_wrapper. You can not grab a temporary with an lvalue reference in your lam through auto&.
for that line, you can simply use
lam(x);
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.
I am trying to solve a simple Fibonacci problem using the lambda function, but I came across this error and I cant solve it.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string str;
auto N{0};
auto i{0};
cout<<"Digite o valor de N desejado: ";
getline(cin,str); //pega linha
stringstream(str) >> N;
if (N == 0){cout<<0;}
else if (N == 1){cout<<1;}
else
{
vector<int> v{0,1}; //cria vetor v
for_each(v.begin(),N,
[&](){
v.push_back(v[i]+v[i+1]);
i++;
});
i = 0;
for_each(v.begin(),N,
[&](){
cout<<v[i];
i++;
});
}
return 0;
}
And the error is the following:
quest1.cpp: In function ‘int main()’: quest1.cpp:30:4: error: no matching function for call to ‘for_each(std::vector<int>::iterator, int&, main()::<lambda()>)’ });
^ In file included from /usr/include/c++/6.3.1/algorithm:62:0,
from quest1.cpp:5: /usr/include/c++/6.3.1/bits/stl_algo.h:3763:5: note: candidate: template<class _IIter, class _Funct> _Funct std::for_each(_IIter,
_IIter, _Funct)
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
^~~~~~~~ /usr/include/c++/6.3.1/bits/stl_algo.h:3763:5: note: template argument deduction/substitution failed: quest1.cpp:30:4: note: deduced conflicting types for parameter ‘_IIter’ (‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ and ‘int’) });
^ quest1.cpp:38:5: error: no matching function for call to ‘for_each(std::vector<int>::iterator, int&, main()::<lambda()>)’
});
^ In file included from /usr/include/c++/6.3.1/algorithm:62:0,
from quest1.cpp:5: /usr/include/c++/6.3.1/bits/stl_algo.h:3763:5: note: candidate: template<class _IIter, class _Funct> _Funct std::for_each(_IIter,
_IIter, _Funct)
for_each(_InputIterator __first, _InputIterator __last, _Function __f)
^~~~~~~~ /usr/include/c++/6.3.1/bits/stl_algo.h:3763:5: note: template argument deduction/substitution failed: quest1.cpp:38:5: note: deduced conflicting types for parameter ‘_IIter’ (‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’ and ‘int’)
});
There's two problems in your code. One (already covered by other answers), you're passing the number of iterations as the second parameter to std::for_each, but it actually expects an end iterator. std::for_each(a, b, f) is designed to iterate from iterator a to iterator b and call f on each element in that range.
The second problem is more fundamental: if you modify the vector while iterating over it, you'll get Undefined Behaviour because any modification operation invalidates all iterators to the vector.
Looking at your code, it seems you want the first loop to a normal counting loop and not iteration over the container. The second loop could be done with for_each and a lambda:
vector<int> v{0,1};
for (int i = 0; i < N; ++i) {
v.push_back(v[i] + v[i+1]);
}
for_each(v.begin(), v.end(),
[](int element) {
cout << element;
}
);
Notice that the functor used in for_each is not nullary: the algorithm will pass the element to it.
Alternatively, the printing functionality could be implemented without lambdas:
copy(v.begin(), v.end(), ostream_iterator<int>(cout));
Or, if you prefer to keep the loop, you could just as well use a range-based for loop instead of for_each. The code will be shorter and [subjective]easier to read[/subjective]:
for (int elem : v) {
std::cout << elem;
}
std::for_each requires (as the error tries to tell you) an iterator where to start looping and an iterator where to end. You however are passing an iterator and an int, which are "conflicting types". If you want to loop over an whole vector do something like that:
std::vector<int> v{1, 2, 3};
std::for_each(v.begin(), // start at the front
v.end(), // loop over each element
[&] (int& i) {
i++;
});
If you just need to loop over a part of the vector do that
std::vector<int> v{1, 2, 3};
std::for_each(v.begin(), // start at the front
v.begin() + 2, // loop over the first two elements
[&] (int& i) {
i++;
});
You are not using the for_each function correctly. C++ does not know the signature you are using. Please refer to the documentation, e.g. for_each.
The compiler says exactly that. The second parameter of the for_each you are calling is of type int&, but the signature is for_each(InputIterator, InputIterator, Function) and not for_each(InputIterator, int&, Function), so it fails to compile.
While practicing the use of lambdas, I wrote this program which is supposed to sort a list of pairs by their second element (an int).
#include <iostream>
#include <algorithm>
#include <list>
using namespace std;
int main()
{
list<pair <string, int>> s = {{"two", 2}, {"one", 1}, {"three", 3}};
sort(s.begin(), s.end(), [](pair<string,int> a, pair<string, int> b) -> bool {
return (a.second) > (b.second);
});
for_each(s.begin(), s.end(), [](pair<string, int> a) {
cout << a.first << " " << a.second << endl;
});
}
I get those errors, though:
c:\qt\qt5.2.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_algo.h:5513: error: no match for 'operator-' (operand types are 'std::_List_iterator<std::pair<std::basic_string<char>, int> >' and 'std::_List_iterator<std::pair<std::basic_string<char>, int> >')
std::__lg(__last - __first) * 2, __comp);
^
c:\qt\qt5.2.0\tools\mingw48_32\lib\gcc\i686-w64-mingw32\4.8.0\include\c++\bits\stl_algo.h:2245: ошибка: 'void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = std::_List_iterator<std::pair<std::basic_string<char>, int> >; _Compare = main()::__lambda0]', declared using local type 'main()::__lambda0', is used but never defined [-fpermissive]
__final_insertion_sort(_RandomAccessIterator __first,
^
What is wrong with my code?
You may not use std::sort with sequential containers such as std::list or std::forward_list because they have no random access iterator that is required by the standard algorithm std::sort. By this reason the both containers have their own member functions sort.
In you case the code will look the following way:
#include <iostream>
#include <list>
#include <string>
using namespace std;
int main()
{
list<pair <string, int>> s = {{"two", 2}, {"one", 1}, {"three", 3}};
s.sort( []( const pair<string,int> &a, const pair<string,int> &b ) { return a.second > b.second; } );
for ( const auto &p : s )
{
cout << p.first << " " << p.second << endl;
}
}
Take into account that you need to include header <string> otherwise your program will not be compiled with other compilers.
std::sort requires random access iterators, which std::list does not have. But you can use std::list::sort instead.
s.sort([](const pair<string,int>& a, const pair<string,int>& b)
{
return (a.second) > (b.second);
});
where I have made the parameters of the predicate const references, since there is no need to copy them, and doing so might incur some unnecessary overhead.