I want to convert this simple code:
void setZComp(Imath::V3f& pt)
{
pt.z = 0.0;
}
int myfunc()
{
...
std::vector<Imath::V3f> vec(5,Imath::V3f(1.0,1.0,1.0));
std::for_each(vec.begin(),vec.end(),boost::bind(&setZComp,_1));
...
}
to something like that, in order to not have setZComp declared outside but some sort of inline declaration
int myfunc()
{
...
boost::function<double(Imath::V3f&)> f = (boost::lambda::_1 ->* &Imath::V3f::z = 0.0) ;
std::for_each(vec.begin(),vec.end(),boost::bind(&f,_1));
...
}
I'm quite new to Boost Bind and Lambda and I don't know if this can be done in some way. Obviously the code above does not work.
Are you using a sledgehammer to break a nut? Sometimes, I think it is simpler to just use a normal for loop and set the variable explicitly yourself. This makes the code much easier to read and maintain.
typedef std::vector<Imath::V3f> V3fVector;
V3fVector vec(5,Imath::V3f(1.0,1.0,1.0));
for (V3fVector::iterator i = vec.begin(), iEnd = vec.end(); iEnd != i; ++i)
i->z = 0.0;
As much as boost bind is useful, its also a syntactical mess that make simple code unreadable.
If you cannot use a C++11 lambda, then you can use boost::lambda::bind.
So in your case something like the following:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
A full example since I don't know your internals:
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
std::for_each(vec.begin(), vec.end(), boost::lambda::bind(&S::i, boost::lambda::_1) = 5);
std::cout << vec.front().i << std::endl; // outputs 5
return 0
}
You might also consider taking a look at boost::phoenix. I think it's a more fully fleshed out implementation of functional programming for c++ than the lambda library.
As explained in the section Member variables as targets:
A pointer to a member variable is not really a function, but the first argument to the [boost::lambda::bind] function can nevertheless be a pointer to a member variable. Invoking such a bind expression returns a reference to the data member.
So to construct a lambda expression that accesses the z member, you can use:
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1)
The returned object can itself be used in other expressions. For example,
boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0
means "obtain the double ref to the z member of the first argument (type Imath::V3f&) and assign the value 0.0".
You can then use this lambda with Boost.Function and std::for_each:
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
For reference, here is a complete, compilable example:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
namespace Imath
{
class V3f
{
public:
double x, y, z;
V3f(double x_, double y_, double z_)
: x(x_), y(y_), z(z_)
{
}
friend std::ostream& operator<<(std::ostream& os, const V3f& pt) {
return (os << '(' << pt.x << ", " << pt.y << ", " << pt.z << ')');
}
};
}
int main()
{
std::vector<Imath::V3f> vec(5, Imath::V3f(1.0, 1.0, 1.0));
boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);
std::vector<Imath::V3f>::iterator it, end = vec.end();
for (it = vec.begin(); it != end; ++it) {
std::cout << *it << std::endl;
}
return EXIT_SUCCESS;
}
Outputs:
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
If you have access to a recent version of g++ with C++11 support, or MSVC 2010, you could do the following:
int myfunc()
{
...
std::for_each(vec.begin(),vec.end(),[](Imath::V3f& pt){ pt.z = 0.0; });
...
}
If you want to use boost::lambda, I sometimes find it cleaner to declare a "pointer-to-member" variable immediately before the line that contains the lambda, which then allows you to use the ->* operator instead of using boost::lambda::bind.
However, as Alan pointed out, a simple loop here might be the simplest solution. Use BOOST_FOREACH to make it even simpler.
Here's a modified version of mkaes's sample implementation that uses operator ->* instead of bind, and it also shows how to use BOOST_FOREACH as an alternative.
#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>
// I like to provide alternate names for the boost::lambda placeholders
boost::lambda::placeholder1_type& arg1 = boost::lambda::_1 ;
boost::lambda::placeholder2_type& arg2 = boost::lambda::_2 ;
boost::lambda::placeholder3_type& arg3 = boost::lambda::_3 ;
struct S
{
S():i(0){};
int i;
};
int main()
{
std::vector<S> vec;
vec.push_back(S());
// Define this pointer-to-member so we can
// use it in the lambda via the ->* operator
int S::* i = &S::i ;
std::for_each(vec.begin(), vec.end(), &arg1->*i = 5);
std::cout << vec.front().i << std::endl; // outputs 5
// Alternatively, just use a simple foreach loop
BOOST_FOREACH( S & s, vec )
{
s.i = 6 ;
}
std::cout << vec.front().i << std::endl; // outputs 6
return 0 ;
}
Related
I have a set of integers {1,2}. I want to produce "Transform#1, Transform#2" where each element is tranformed and then result is accumulated with a delimiter.
What would be the easiest way to accomplish this? Do we have "folds", "maps" in c++?
We dont use boost.
You can use std::transform and std::accumulate
int main()
{
std::vector<int> v1 {1,2,3};
std::vector<std::string> v2;
std::transform(begin(v1), end(v1), std::back_inserter(v2), [](auto const& i) {
return std::string("Transform#") + std::to_string(i);
});
std::string s = std::accumulate(std::next(begin(v2)), end(v2), v2.at(0), [](auto const& a, auto const& b) {
return a + ", " + b;
});
std::cout << s;
}
prints Transform#1, Transform#2, Transform#3
You may want to use Range Adaptors. Boost already has them and they are coming to the standard with C++20.
Take a look at the boost::adaptors::transformed example here.
Also, check out the reference to get a better picture of what operations are supported by adaptors.
In the end, you can achieve much cleaner code and the performance difference is negligible (unlike in some other languages, where using this style of programming incurs heavy performance costs).
If you can stand a trailing separator, the following function can transform any iterable range of data { X, ..., Z } to the string "<tag>X<sep>...<sep><tag>Z<sep>".
Code
template <class InputIt>
std::string f(InputIt begin, InputIt end, std::string_view separator = ", ", std::string_view tag = "Transform#")
{
std::stringstream output;
std::transform(begin, end,
std::ostream_iterator<std::string>(output, separator.data()),
[tag](auto const& element){ return std::string{tag} + std::to_string(element); }
);
return output.str();
}
It works by transforming each element from the range into a stream iterator.
Usage
int main()
{
std::set<int> const data{1, 2, 3}; // works with vector, string, list, C-arrays, etc.
std::cout << f(begin(data), end(data)) << '\n';
// prints Transform#1, Transform#2, Transform#3,
}
Live demo
You can perform a fold using simply std::accumulate
#include <set>
#include <string>
#include <iostream>
#include <numeric>
int main()
{
auto transformation = [](int number) { return "Transform#" + std::to_string(number); };
auto transform_and_fold = [&transformation](std::string init, int number) { return std::move(init) + ", " + transformation(number); };
std::set<int> numbers{1, 2};
std::cout << std::accumulate(std::next(numbers.begin()), numbers.end(), transformation(*numbers.begin()), transform_and_fold);
}
Outputs
Transform#1, Transform#2
Assuming that I correctly understand the problem, the following straightforward implementation also looks very simple and easy.
This function works in C++11 and over:
DEMO with 5 test cases
std::string concatenate(
const std::vector<int>& indecies,
const std::string& delimiter = ", ",
const std::string& tag = "Transform#")
{
if(indecies.empty()){
return "";
}
std::string s(tag + std::to_string(indecies[0]));
for(auto it = indecies.begin()+1; it != indecies.cend(); ++it){
s += (delimiter + tag + std::to_string(*it));
}
return s;
}
(BTW, as for this function concatenate, if indecies is empty, the return value is also an empty string, not exceptions (AndreasDM's one) or UB (Everlight's one).
And if indecies has only a single element, for instance indecies={1}, then result is "Transform#1”, not "Transform#1, ”(YSC's one) or ", Transform#1”(sakra's one).
These are different from other answers and this function will be more simpler if this handling is removed.)
Although the performance may not be a focal point, the above function can be slightly optimized by pre-reserving the minimum capacity to save the resulted string by std::basic_string::reserve as follows.
Here +1 in *.size()+1 means the minimum length of a number character.
I also removed delimiter+tag in the for-loop.
This still looks simple:
DEMO with 5 test cases
std::string concatenate_fast(
const std::vector<int>& indecies,
std::string delimiter = ", ",
const std::string& tag = "Transform#")
{
if(indecies.empty()){
return "";
}
std::string s(tag + std::to_string(indecies[0]));
delimiter += tag;
s.reserve((tag.size()+1) + (indecies.size()-1)*(delimiter.size()+1));
for(auto it = indecies.begin()+1; it != indecies.cend(); ++it){
s += (delimiter + std::to_string(*it));
}
return s;
}
I have also tested the performance of these functions and some proposed answers as follows.
These tests are done by Quick C++ Benchmark within gcc-8.2, C++17 and O3 optimization.
Since std::transform_reduce is still not available in Quick C++ Benchmark, I haven’t tested it.
The above concatenate_fast shows best performance at least in these cases and concatenate is second best.
Finally, just personally, taking the balance of the readability and the performance into account, I would like to propose the above concatenate as a solution:
- Performance test with size 2 and 8. (DEMO)
- Performance test with size 16 and 32. (DEMO)
Unless you have some other requirement to preserve the intermediate tranformed list, storing it is suboptimal. You can just call std::accumulate and do both operations on the fly:
#include <cstdio>
#include <iterator>
#include <numeric>
int main ( )
{
int const input [] = { 1, 2, 3, 4, 5, 6 };
// computes sum of squares
auto const add_square = [] ( int x, int y ) { return x + y * y; };
int result = std::accumulate
( std::cbegin (input)
, std::cend (input)
, 0
, add_square
);
std::printf ( "\n%i\n", result );
return 0;
}
If you have the luxury of using C++17, there is a standard library algorithm which does exactly what you need. Here is an example:
#include <iterator>
#include <iostream>
#include <numeric>
#include <string>
int main()
{
auto input = {1, 2, 3};
std::cout << std::transform_reduce(
std::cbegin(input), std::cend(input),
std::string("Result:"),
[](const std::string & left, const std::string & right) { return left + " " + right; },
[](int value) { return "Transform#" + std::to_string(value); }
) << "\n";
}
In python, we can do this:
int_list = [1, 2, 3, 4, 5]
print(sum(int_list)) # prints 15
float_tuple = (1.2, 3.4, 9.9)
print(sum(float_tuple)) # prints 14.5
The sum function takes any iterable of elements that know how to be added to each other and to 0 and produces the sum.
I wanted to make an identical function in C++11. I'm aware that there exists the accumulate method, but I want a function that takes a single parameter. Essentially, I want to know how to make the following code compile:
#include <string>
#include <iostream>
#include <vector>
#include <deque>
#include <list>
template<typename iterable>
auto sum(iterable iterable_) {
auto it = iterable_.begin();
auto end = iterable_.end();
if (it == end) {
return 0;
}
auto res = *(it++);
while (it != end) {
res += *it++;
}
return res;
}
int main() {
std::vector<int> int_vector = {0, 1, 2, 3, 4, 5};
std::cout << sum(int_vector) << '\n'; // prints 15
std::deque<int> int_deque = {4, 5, 7};
std::cout << sum(int_deque) << '\n'; // prints 16
std::list<float> float_list = {1.2, 3.4, 9.9};
std::cout << sum(float_list) << '\n'; // should print 14.5, but produces error.
}
This code almost works. The issue is that auto sees the return 0; in the case that the iterable is empty and it assumes that the function must return an int. Then it sees that the float version returns a float and it gets confused. Is there any way to tell the compiler to, say return float(0) if it sees that the return later on returns float?
Yes, you can make this work at least for standard containers.
A standard container defines a type alias named value_type for the type of value stored in that container. For an empty container, you can return a value-constructed object of this type:
template<typename iterable>
auto sum(iterable const &iterable_) {
auto it = iterable_.begin();
auto end = iterable_.end();
if (it == end) {
return typename iterable::value_type();
}
auto res = *(it++);
while (it != end) {
res += *it++;
}
return res;
}
This does depend on the contained type being default-constructible, but that's probably not a major problem (certainly works for primitive types like int and float).
If you want something to work with any C++11 range (that is, anything that you can iterate over in a range-based for expression - including arrays as well as containers that have free begin and end), we can just add some using-declarations and wrap std::accumulate
template <class Range>
auto sum(Range&& range) {
using std::begin;
using std::end;
using T = std::decay_t<decltype(*begin(range))>;
return std::accumulate(begin(range), end(range), T{});
}
If you don't want to wrap accumulate, then you can just re-implement that loop as well to do the same thing.
The following approach works even with non-standard containers; as long as something implements begin() and end(), in a reasonable way.
#include <list>
#include <iostream>
#include <type_traits>
template<typename iterable>
auto sum(iterable && iterable_) {
auto it = iterable_.begin();
auto end = iterable_.end();
typedef typename std::remove_reference<decltype(*it)>::type value_type;
if (it == end) {
return value_type(0);
}
auto res = *(it++);
while (it != end) {
res += *it++;
}
return res;
}
int main() {
std::list<float> float_list = {1.2, 3.4, 9.9};
std::cout << sum(float_list) << '\n'; // works now.
}
For educational purposes
I have a function integrate which takes in a std::function as a parameter.
double calculus::integralSimple(std::function<double(double)> fn, double begin, double end)
{
double integral = 0;
for (long double i = begin; i < end; i += _step)
{
integral += fn(i) * _step; // _step defined in class
}
return integral;
}
Currently I am calling this function from main.cpp using
calculus cl;
std::cout << cl.integralSimple(calculus::identity,0,1);
std::cout << cl.integralSimple([](double x) { return x*x; }, 0, 1);
where identity is a static function defined in calculus.h and the other uses a lambda function.
I was wondering whether I could make the syntax easier for the user and closer to a mathematics way.
So what I would prefer is that the user just have to type:
std::cout << cl.integralSimple( x*x ,0,1); // Always take a function of this form
std::cout << cl.integralSimple( x*sin(x) - x*x ,0,1);
Is there any way to achieve this in C++?
That is exactly what Boost.Lambda was designed for. The syntax would look like this:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
const double PI =3.141592653589793238463;
double func(double v) { return std::sin(v); } // to avoid having to
// cast std::sin
int main()
{
using namespace boost::lambda;
std::vector<double> v = {0, PI / 4, PI / 2, PI};
std::for_each(v.begin(), v.end(),
std::cout << _1 * bind(func, _1) - _1 * _1 << '\n'
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑
// to delay invocation of func
);
}
Whether that's better than the C++11 lambda syntax or not is entirely up to you.
Note that thanks to C++14 and some abuse of features, we can actually write exactly the expression you want too:
auto x = _1;
auto sin(decltype(_1) ) {
return bind(static_cast<double(*)(double)>(std::sin), _1);
}
With that, we can do:
std::for_each(v.begin(), v.end(),
std::cout << x * sin(x) - x * x << '\n');
Which will print exactly the same thing the original example did. Just... more cryptically.
I am playing with boost::range and boost::lambda with following example to compare two numbers and get the element out which has same number.
#include <iostream>
#include <boost/optional.hpp>
#include <boost/range/algorithm/find_if.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/utility/compare_pointees.hpp>
template <class Range, class Predicate>
boost::optional<typename boost::range_value<Range>::type>
search_for(const Range& r, Predicate pred)
{
BOOST_AUTO (it, boost::find_if(r, pred));
if (it == boost::end(r))
return boost::none;
return *it;
}
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 3;
std::vector<int*> m = {&a, &b, &c};
if (boost::optional<int*> number =
search_for(m, boost::equal_pointees(???, &d))) {
std::cout << "found:" << (*number.get()) << std::endl;
}
else {
std::cout << "not found" << std::endl;
}
}
What should I use for ??? above in search_for function?
I believe it could be very simple but don't know how to do it. I can use the boost::bind or std::bind2d, etc to compare but was thinking if there is any elegant way to do it. Also, this code sample could be restructured to much simpler one but I am just learning.
With boost::lambda, it looks like this:
namespace ll = boost::lambda;
search_for(m, *ll::_1 == d)
Which is far less complicated than taking a pointer to d just so you can use equal_pointees.
In C++, is there a way to call a function on each element of a vector, without using a loop running over all vector elements? Something similar to a 'map' in Python.
You've already gotten several answers mentioning std::for_each.
While these respond to the question you've asked, I'd add that at least in my experience, std::for_each is about the least useful of the standard algorithms.
I use (for one example) std::transform, which is basically a[i] = f(b[i]); or result[i] = f(a[i], b[i]); much more frequently than std::for_each. Many people frequently use std::for_each to print elements of a collection; for that purpose, std::copy with an std::ostream_iterator as the destination works much better.
Yes: std::for_each.
#include <algorithm> //std::for_each
void foo(int a) {
std::cout << a << "\n";
}
std::vector<int> v;
...
std::for_each(v.begin(), v.end(), &foo);
On C++ 11: You could use a lambda. For example:
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
ref: http://en.cppreference.com/w/cpp/algorithm/for_each
If you have C++11, there's an even shorter method: ranged-based for. Its purpose is exactly this.
std::vector<int> v {1,2,3,4,5};
for (int element : v)
std::cout << element; //prints 12345
You can also apply references and const to it as well, when appropriate, or use auto when the type is long.
std::vector<std::vector<int>> v {{1,2,3},{4,5,6}};
for (const auto &vec : v)
{
for (int element : vec)
cout << element;
cout << '\n';
}
Output:
123
456
The OP mentions the map function in Python.
This Python function actually applies a function to every element of a list (or iterable) and returns a list (or iterable) that collects all results.
In other words, it does something like this:
def f( x ) :
""" a function that computes something with x"""
# code here
return y
input = [ x1, x2, x3, ... ]
output = map( func, input )
# output is now [ f(x1), f(x2), f(x3), ...]
Hence, the closest C++ standard-library equivalent to Python's map is actually std::transform (from the <algorithm> header).
Example usage is as follows:
#include <vector>
#include <algorithm>
using namespace std;
double f( int x ) {
// a function that computes the square of x divided by 2.0
return x * x / 2.0 ;
}
int main( ) {
vector<int> input{ 1, 5, 10 , 20};
vector<double> output;
output.resize( input.size() ); // unfortunately this is necessary
std::transform( input.begin(), input.end(), output.begin(), f );
// output now contains { f(1), f(5), f(10), f(20) }
// = { 0.5, 12.5, 50.0, 200.0 }
return 0;
}
Use for_each:
// for_each example
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void myfunction (int i) {
cout << " " << i;
}
struct myclass {
void operator() (int i) {cout << " " << i;}
} myobject;
int main () {
vector<int> myvector;
myvector.push_back(10);
myvector.push_back(20);
myvector.push_back(30);
cout << "myvector contains:";
for_each (myvector.begin(), myvector.end(), myfunction);
// or:
cout << "\nmyvector contains:";
for_each (myvector.begin(), myvector.end(), myobject);
cout << endl;
return 0;
}
You can use std::for_each which takes a pair of iterators and a function or functor.
Thought I would share std::ranges equivalents for for_each and transform, should anyone prefer them:
std::vector<int> v;
std::ranges::for_each(v,[](const auto& n) {});
const auto squared = v | std::views::transform([](const auto& n) { return n*2; });
Running on godbolt: https://godbolt.org/z/zYME6b