What can be wrong this piece of code.
I'm trying to call countLessThan3 by instantiating with std::vector.
// 3. Lambdas
template<typename T>
const auto countLessThan3(const T & vec, int value)
{
const auto count = std::count(vec.begin(), vec.end(),
[](int i){ return i < 3;}
);
return count;
}
int main(int argc, char const *argv[])
{
// 3
std::vector<int> vector = {1, 2, 3, 4, 5, 2, 2, 2};
countLessThan3<std::vector<int>>(vector, 3);
return 0;
}
compiled with g++ -std=c++14 1.cpp -o 1 on linux.
Ther are some problems:
The code uses std::count, but a lambda is passed, so it should be std::count_if instead.
value is passed to the function as a parameter, but it is not used and there is an hard coded 3 in the lambda.
Other minor issues are fixed in the snippet below
#include <iostream>
#include <vector>
#include <algorithm>
template<typename T>
auto countLessThan(const T & vec, typename T::value_type value)
{
return std::count_if(vec.begin(), vec.end(),
[value](typename T::value_type i){ return i < value;}
);
}
int main()
{
std::vector<int> vector = {1, 2, 3, 4, 5, 2, 2, 2};
std::cout << countLessThan(vector, 3) << '\n';
return 0;
}
Related
Is there a container adapter that would reverse the direction of iterators so I can iterate over a container in reverse with range-based for-loop?
With explicit iterators I would convert this:
for (auto i = c.begin(); i != c.end(); ++i) { ...
into this:
for (auto i = c.rbegin(); i != c.rend(); ++i) { ...
I want to convert this:
for (auto& i: c) { ...
to this:
for (auto& i: std::magic_reverse_adapter(c)) { ...
Is there such a thing or do I have to write it myself?
Actually Boost does have such adaptor: boost::adaptors::reverse.
#include <list>
#include <iostream>
#include <boost/range/adaptor/reversed.hpp>
int main()
{
std::list<int> x { 2, 3, 5, 7, 11, 13, 17, 19 };
for (auto i : boost::adaptors::reverse(x))
std::cout << i << '\n';
for (auto i : x)
std::cout << i << '\n';
}
Actually, in C++14 it can be done with a very few lines of code.
This is a very similar in idea to #Paul's solution. Due to things missing from C++11, that solution is a bit unnecessarily bloated (plus defining in std smells). Thanks to C++14 we can make it a lot more readable.
The key observation is that range-based for-loops work by relying on begin() and end() in order to acquire the range's iterators. Thanks to ADL, one doesn't even need to define their custom begin() and end() in the std:: namespace.
Here is a very simple-sample solution:
// -------------------------------------------------------------------
// --- Reversed iterable
template <typename T>
struct reversion_wrapper { T& iterable; };
template <typename T>
auto begin (reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template <typename T>
auto end (reversion_wrapper<T> w) { return std::rend(w.iterable); }
template <typename T>
reversion_wrapper<T> reverse (T&& iterable) { return { iterable }; }
This works like a charm, for instance:
template <typename T>
void print_iterable (std::ostream& out, const T& iterable)
{
for (auto&& element: iterable)
out << element << ',';
out << '\n';
}
int main (int, char**)
{
using namespace std;
// on prvalues
print_iterable(cout, reverse(initializer_list<int> { 1, 2, 3, 4, }));
// on const lvalue references
const list<int> ints_list { 1, 2, 3, 4, };
for (auto&& el: reverse(ints_list))
cout << el << ',';
cout << '\n';
// on mutable lvalue references
vector<int> ints_vec { 0, 0, 0, 0, };
size_t i = 0;
for (int& el: reverse(ints_vec))
el += i++;
print_iterable(cout, ints_vec);
print_iterable(cout, reverse(ints_vec));
return 0;
}
prints as expected
4,3,2,1,
4,3,2,1,
3,2,1,0,
0,1,2,3,
NOTE std::rbegin(), std::rend(), and std::make_reverse_iterator() are not yet implemented in GCC-4.9. I write these examples according to the standard, but they would not compile in stable g++. Nevertheless, adding temporary stubs for these three functions is very easy. Here is a sample implementation, definitely not complete but works well enough for most cases:
// --------------------------------------------------
template <typename I>
reverse_iterator<I> make_reverse_iterator (I i)
{
return std::reverse_iterator<I> { i };
}
// --------------------------------------------------
template <typename T>
auto rbegin (T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
// const container variants
template <typename T>
auto rbegin (const T& iterable)
{
return make_reverse_iterator(iterable.end());
}
template <typename T>
auto rend (const T& iterable)
{
return make_reverse_iterator(iterable.begin());
}
Got this example from cppreference. It works with:
GCC 10.1+ with flag -std=c++20
#include <ranges>
#include <iostream>
int main()
{
static constexpr auto il = {3, 1, 4, 1, 5, 9};
std::ranges::reverse_view rv {il};
for (int i : rv)
std::cout << i << ' ';
std::cout << '\n';
for(int i : il | std::views::reverse)
std::cout << i << ' ';
}
If you can use range v3 , you can use the reverse range adapter ranges::view::reverse which allows you to view the container in reverse.
A minimal working example:
#include <iostream>
#include <vector>
#include <range/v3/view.hpp>
int main()
{
std::vector<int> intVec = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto const& e : ranges::view::reverse(intVec)) {
std::cout << e << " ";
}
std::cout << std::endl;
for (auto const& e : intVec) {
std::cout << e << " ";
}
std::cout << std::endl;
}
See DEMO 1.
Note: As per Eric Niebler, this feature will be available in C++20. This can be used with the <experimental/ranges/range> header. Then the for statement will look like this:
for (auto const& e : view::reverse(intVec)) {
std::cout << e << " ";
}
See DEMO 2
This should work in C++11 without boost:
namespace std {
template<class T>
T begin(std::pair<T, T> p)
{
return p.first;
}
template<class T>
T end(std::pair<T, T> p)
{
return p.second;
}
}
template<class Iterator>
std::reverse_iterator<Iterator> make_reverse_iterator(Iterator it)
{
return std::reverse_iterator<Iterator>(it);
}
template<class Range>
std::pair<std::reverse_iterator<decltype(begin(std::declval<Range>()))>, std::reverse_iterator<decltype(begin(std::declval<Range>()))>> make_reverse_range(Range&& r)
{
return std::make_pair(make_reverse_iterator(begin(r)), make_reverse_iterator(end(r)));
}
for(auto x: make_reverse_range(r))
{
...
}
Does this work for you:
#include <iostream>
#include <list>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator_range.hpp>
int main(int argc, char* argv[]){
typedef std::list<int> Nums;
typedef Nums::iterator NumIt;
typedef boost::range_reverse_iterator<Nums>::type RevNumIt;
typedef boost::iterator_range<NumIt> irange_1;
typedef boost::iterator_range<RevNumIt> irange_2;
Nums n = {1, 2, 3, 4, 5, 6, 7, 8};
irange_1 r1 = boost::make_iterator_range( boost::begin(n), boost::end(n) );
irange_2 r2 = boost::make_iterator_range( boost::end(n), boost::begin(n) );
// prints: 1 2 3 4 5 6 7 8
for(auto e : r1)
std::cout << e << ' ';
std::cout << std::endl;
// prints: 8 7 6 5 4 3 2 1
for(auto e : r2)
std::cout << e << ' ';
std::cout << std::endl;
return 0;
}
Sorry but with current C++ (apart from C++20) all these solutions do seem to be inferior to just use index-based for. Nothing here is just "a few lines of code". So, yes: iterate via a simple int-loop. That's the best solution.
template <typename C>
struct reverse_wrapper {
C & c_;
reverse_wrapper(C & c) : c_(c) {}
typename C::reverse_iterator begin() {return c_.rbegin();}
typename C::reverse_iterator end() {return c_.rend(); }
};
template <typename C, size_t N>
struct reverse_wrapper< C[N] >{
C (&c_)[N];
reverse_wrapper( C(&c)[N] ) : c_(c) {}
typename std::reverse_iterator<const C *> begin() { return std::rbegin(c_); }
typename std::reverse_iterator<const C *> end() { return std::rend(c_); }
};
template <typename C>
reverse_wrapper<C> r_wrap(C & c) {
return reverse_wrapper<C>(c);
}
eg:
int main(int argc, const char * argv[]) {
std::vector<int> arr{1, 2, 3, 4, 5};
int arr1[] = {1, 2, 3, 4, 5};
for (auto i : r_wrap(arr)) {
printf("%d ", i);
}
printf("\n");
for (auto i : r_wrap(arr1)) {
printf("%d ", i);
}
printf("\n");
return 0;
}
You could simply use BOOST_REVERSE_FOREACH which iterates backwards. For example, the code
#include <iostream>
#include <boost\foreach.hpp>
int main()
{
int integers[] = { 0, 1, 2, 3, 4 };
BOOST_REVERSE_FOREACH(auto i, integers)
{
std::cout << i << std::endl;
}
return 0;
}
generates the following output:
4
3
2
1
0
If not using C++14, then I find below the simplest solution.
#define METHOD(NAME, ...) auto NAME __VA_ARGS__ -> decltype(m_T.r##NAME) { return m_T.r##NAME; }
template<typename T>
struct Reverse
{
T& m_T;
METHOD(begin());
METHOD(end());
METHOD(begin(), const);
METHOD(end(), const);
};
#undef METHOD
template<typename T>
Reverse<T> MakeReverse (T& t) { return Reverse<T>{t}; }
Demo.
It doesn't work for the containers/data-types (like array), which doesn't have begin/rbegin, end/rend functions.
#include <algorithm>
#include <array>
#include <iostream>
int main() {
std::array<int, 10> s{5, 7, 4, 2, 8, 6, 1, 9, 0, 3};
struct {
bool operator()(int a, int b) const
{
return a < b;
}
} customLess;
std::sort(s.begin(), s.end(), customLess);
for (auto a : s) {
std::cout << a << " ";
}
std::cout << '\n';
return 0;
}
I want to sort the array using std : : sort. The code above works fine, but when I try with template array in my main task (GArr<int, 5> arr{5, 2, 3, 4, 1};) the compiler gives the following
error: no match for 'operator-' (operand types are 'Iterator' and
'Iterator')|
How can I fix it?
So basically, I want to create a function like this:
total_sum(1, 2, 5, 4, 2) // return 14
total_sum(5, 6, 2) // return 13
One way that I can use is ellipsis, something like this:
#include <cstdarg>
int total_sum(int count, ...)
{
int sum{0};
va_list list;
va_start(list, count);
for (int arg{0}; arg < count; ++arg)
{
sum += va_arg(list, int);
}
va_end(list);
return sum;
}
But when I call total_sum(), I have to provide an extra argument. So in the example, I have to call:
total_sum(5, 1, 2, 5, 4, 2);
total_sum(3, 5, 6, 2);
which I don't really like. Also, ellipsis is really prone to error, so I want to stay away from them.
Another way I can think of is using some container:
#include <vector>
int total_sum(std::vector<int> values)
{
int sum{0};
for(const auto &i : values)
{
sum += i;
}
return sum;
}
and I call it like:
total_sum({1, 2, 5, 4, 2});
total_sum({3, 5, 6, 2});
But, I want to not have those curly braces, so what can I do? Is there some C++ feature that allows me to do this?
Some relevant links: restrict variadic template arguments, fold expression, parameter packs and a
C++11 "equivalent" of fold expressions
Use C++17 fold expression:
template<class... Args>
constexpr auto total_sum(const Args&... args) {
return (args + ... + 0);
}
static_assert(total_sum(1, 2, 5, 4, 2) == 14);
static_assert(total_sum(3, 5, 6, 2) == 16);
In C++11 and newer you can use template parameter packs to create a recursive implementation, like this:
#include <iostream>
// base function
int total_sum()
{
return 0;
}
// recursive variadic function
template<typename T, typename... Targs>
int total_sum(T firstValue, Targs... Fargs)
{
return firstValue + total_sum(Fargs...);
}
int main(int, char **)
{
int s = total_sum(1, 5, 10, 20);
std::cout << "sum is: " << s << std::endl;
return 0;
}
Running the above program produces this output:
sum is: 36
All of the code below is is based on this article.
You can also do this kind-of C++11 "equivalent" of fold expressions:
#include <iostream>
#include <algorithm>
#include <utility>
#include <type_traits>
/*
Overload a total_sum() function with no arguments.
so it works when calling total_sum() with no argument.
*/
int total_sum()
{
return 0;
}
template<typename ... I>
int total_sum(const I &... i)
{
int result{};
static_cast<void>(std::initializer_list<int>{(result += i, 0)... });
return result;
}
int main()
{
std::cout << total_sum() << '\n';
std::cout << total_sum(1, 2, 5, 4, 2) << '\n';
std::cout << total_sum(5, 6, 2) << '\n';
}
See this online!
This one can add anything that can convert to an add-able value:
#include <iostream>
#include <algorithm>
#include <utility>
#include <type_traits>
int total_sum()
{
return 0;
}
template<typename ... V>
typename std::common_type<V...>::type total_sum(const V &... v)
{
typename std::common_type<V...>::type result = {};
static_cast<void>(std::initializer_list<int>{ (result += v, 0)... });
return result;
}
int main()
{
std::cout << total_sum() << '\n';
std::cout << total_sum(5, 6, 2) << '\n';
}
See this online!
The code above can be cleaner using C++14:
#include <iostream>
#include <algorithm>
#include <utility>
#include <type_traits>
int total_sum()
{
return 0;
}
template<typename ... V>
auto total_sum(const V &... v) {
std::common_type_t<V...> result = {};
static_cast<void>(std::initializer_list<int>{ (result += v, 0)... });
return result;
}
int main()
{
std::cout << total_sum() << '\n';
std::cout << total_sum(5, 6, 2) << '\n';
}
See this online!
I have an array std::vector<int> and an enum class Foo : int. Is there a better way to cast or convert than a reinterpret_cast?
std::vector<int> v;
auto& c = *reinterpret_cast<std::vector<Foo>*>(&v);
https://godbolt.org/z/M6ofkF
Combine a static_cast with std::transform.
#include <algorithm>
#include <vector>
#include <cassert>
enum class Foo : int {
A = 0,
B = 1,
C = 2,
D = 3,
E = 4,
F = 5
};
std::vector<Foo> convert(std::vector<int> const &in) {
std::vector<Foo> out;
out.reserve(in.size());
std::transform(in.begin(), in.end(), std::back_inserter(out),
[](int n) { return static_cast<Foo>(n); });
return out;
}
int main() {
std::vector<int> vec{1, 2, 3, 4, 5};
std::vector<Foo> c = convert(vec);
assert(c[3] == Foo::E);
return 0;
}
Reference: How to cast int to enum in C++?
Is there a function similar to accummulate() but provides a unary pre-condition to filter the linear container when performing the operation? I search for accummulate_if but there isn't any. Thanks!
update:
Thanks for all the kind answers. I end up doing it this way:
std::for_each(v.begin(), v.end(), [&](int x){if (Pred) sum += x;});
Must you really use an algorithm?
Something as simple as below won't do?
for (const auto& v: V) if(pred(v)) sum+=v;
Sam's idea is also good. But I would do it with lambda:
sum = accumulate(
V.begin(), V.end(), 0,
[](int a, int b){return pred(b)? a+b: a;}
);
Pass your own binary op to std::accumulate():
#include <iostream>
#include <vector>
#include <numeric>
bool meets_criteria(int value) {
return value >= 5;
}
int my_conditional_binary_op(int a, int b) {
return meets_criteria(b) ? a + b : a;
}
class my_function_object {
private:
int threshold;
public:
my_function_object(int threshold) :
threshold(threshold) {
}
bool meets_criteria(int value) const {
return value >= threshold;
}
int operator()(int a, int b) const {
return meets_criteria(b) ? a + b : a;
}
};
int main() {
std::vector<int> v { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//sum [5...10] = 45
int sum;
sum = std::accumulate(v.begin(), v.end(), 0, my_conditional_binary_op);
std::cout << sum << std::endl;
//Use a function object to maintain states and additional parameters like 'threshold'
sum = std::accumulate(v.begin(), v.end(), 0, my_function_object(5));
std::cout << sum << std::endl;
return sum;
}
No, but you can write it yourself:
template
<
typename InputIterator,
typename AccumulateType,
typename BinaryOperation,
typename Predicate
>
const AccumulateType accumulate_if(
InputIterator first,
const InputIterator last,
AccumulateType init,
BinaryOperation&& binary_op,
Predicate&& predicate)
{
for (; first != last; ++first)
if (predicate(*first)) init = binary_op(init, *first);
return init;
}
Usage:
int main(int argc, char* argv[])
{
std::vector<int> v = {1,2,3,4,5};
std::cout << accumulate_if(v.begin(), v.end(), 0, std::plus<int>(), [] (int n) { return n > 3; });
return 0;
} // outputs 9