This question is a matter of style, since you can always write a for loop or something similar; however, is there a less obtrusive STL or BOOST equivalent to writing:
for (container<type>::iterator iter = cointainer.begin();
iter != cointainer.end();
iter++)
iter->func();
?
Something like (imagined) this:
call_for_each(container.begin(), container.end(), &Type::func);
I think it would be 1) less typing, 2) easier to read, 3) less changes if you decided to change base type/container type.
EDIT:
Thanks for your help, now, what if I wanted to pass some arguments to the member function?
#include <algorithm> // for_each
#include <functional> // bind
// ...
std::for_each(container.begin(), container.end(),
std::bind(&Type::func));
See std::for_each and std::bind documentation for details.
Missed your edit: Anyway here is another way of achieving what you want without using Boost, if ever need be:
std::for_each(foo_vector.begin(), foo_vector.end(),
std::bind(&Foo::func, std::placeholders::_1));
You can use std::for_each or boost's foreach constructs.
Use boost's BOOST_FOREACH or BOOST_REVERSE_FOREACH when you don't want to move the logic into another function.
I found out that boost bind seems to be well suited for the task, plus you can pass additional arguments to the method:
#include <iostream>
#include <functional>
#include <boost/bind.hpp>
#include <vector>
#include <algorithm>
struct Foo {
Foo(int value) : value_(value) {
}
void func(int value) {
std::cout << "member = " << value_ << " argument = " << value << std::endl;
}
private:
int value_;
};
int main() {
std::vector<Foo> foo_vector;
for (int i = 0; i < 5; i++)
foo_vector.push_back(Foo(i));
std::for_each(foo_vector.begin(), foo_vector.end(),
boost::bind(&Foo::func, _1, 1));
}
Since C++11 standard the BOOST approach is standardized with different syntax as the "range-based-loop":
class Foo {
Foo(int x);
void foo();
}
vector<int> list = {Foo(1),Foo(2),Foo(3)};
for(auto &item: list) item.foo();
If you actually want to improve performance rather than just pretty up your code, what you really need is a map function. Eric Sink wrote a .net implementation
Related
so I thought adding unique to vector shouldn't work.
Why does it work for the below code?
Is it cause by not setting copy ctor as "deleted"??
#include <iostream>
#include <vector>
#include <memory>
class Test
{
public:
int i = 5;
};
int main()
{
std::vector<std::unique_ptr<Test>> tests;
tests.push_back(std::make_unique<Test>());
for (auto &test : tests)
{
std::cout << test->i << std::endl;
}
for (auto &test : tests)
{
std::cout << test->i << std::endl;
}
}
There is no copy here, only moves.
In this context, make_unique will produce an instance of unique pointer which is not named, and this push_back sees it as a r-value reference, which it can use as it wants.
It produce pretty much the same result than this code would:
std::vector<std::unique_ptr<Test>> tests;
auto ptr = std::make_unique<Test>();
tests.push_back(std::move(ptr));
This is called move semantics if you want to search more info on the matter. (and this only works from c++11 and beyond)
There are two overloads of std::vector::push_back according to https://en.cppreference.com/w/cpp/container/vector/push_back
In your case you will use the one with rvalue-ref so no copying required.
In the following code I get a warning with MSVC (C4996) that std::copy(errors.begin(),errors.end(),pErrors.get()); is not safe. It writes into the raw pointer. Is there an elegant and safe way to iterate over the elements?
The main goal is to prepare a built-in array for a call to a legacy function:
#include <iostream>
#include <initializer_list>
#include <memory>
#include <algorithm>
void print_errors_old_function(int argument_count,int* pErrors)
{
for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
}
void print_errors(std::initializer_list<int> errors)
{
std::unique_ptr<int[]> pErrors{new int[errors.size()]};
std::copy(errors.begin(),errors.end(),pErrors.get()); // warning C4996
print_errors_old_function(errors.size(),pErrors.get());
}
int main()
{
print_errors({234,253,334});
return 0;
}
It seems a range based for loop is not possible with std::unique_ptr<int[]> and that regular for loop would arguably less readable than std::copy.
You don't need std::unique_ptr. std::vector will work fine, because &v[0] is guaranteed to give you a pointer to the internal buffer, and of course it also has a size() member function you can use to interface with C functions. Since C++11, there's also data(), which looks nicer than &v[0].
#include <iostream>
#include <initializer_list>
#include <vector>
void print_errors_old_function(int argument_count,int* pErrors)
{
for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
}
void print_errors(std::initializer_list<int> errors)
{
std::vector<int> vErrors(errors);
print_errors_old_function(vErrors.size(), &vErrors[0] /* or vErrors.data() in C+11 */ );
}
int main()
{
print_errors({234,253,334});
return 0;
}
Notice how is also gets rid of the warning.
The other answer is correct, but note that were the function like this:
void print_errors_old_function(int argument_count,int* pErrors)
{
for (int i=0;i<argument_count;++i) { std::cerr << "Error" << pErrors[i] << " "; }
delete[] pErrors; // note this function effectively "consumes" the input
}
you wouldn't be able to use this approach, as there is no way to release ownership of the vector's memory. You'd have to make use std::unique_ptr the way you do in your question, but you'd have to use pErrors.release() instead of pErrors.get().
Visual C++ complains because on several functions which are defined in the standard, but it deems them as "unsafe", which makes standard-conforming code non-compilable. Sometimes, Microsoft provides workarounds, which are only available on Visual C++.
What you can do (choose one of these):
make use of the suggested Microsoft's workarounds
disable SDL checks (these checks turn these warnings into errors)
define _SCL_SECURE_NO_WARNINGS in your project. (to disable these warnings)
After going though a question on std::bind, I was wondering if it was possible to hold a vector of functions created by std::bind so I can avoid using std::function and its heavyweight wrapping.
#include <iostream>
#include <functional>
#include <typeinfo>
#include <vector>
int add(int a, int b) {return a + b;}
int main() {
//I believe this here is just a special type of bound function.
auto add2 = std::bind(add, std::placeholders::_1, 2);
auto add3 = std::bind(add, std::placeholders::_1, 3);
//Yup.
std::cout << typeid(add2).name() << std::endl;
//Here's the type of the second function
std::cout << typeid(add3).name() << std::endl;
//Is there a nicer way to do this?
std::vector<decltype(std::bind(add, std::placeholders::_1, 1))> vec;
return 0;
}
Although it's possible of to create a vector of std::bind functions, is there a way I don't have to provide a specific case of a bound function in order to declare a container without an empty/dummy type of a function made from std::bind?
So, it appears that this isn't possible--std::bind doesn't appear to have a normally nameable/explicit type--the type is usually generated according to the signature of the bound function, and doesn't appear to be specifiable. Using std::function seems to be the only way to wrap std::bind functions and store them in a vector.
Even for lambdas, this doesn't seem possible--using a wrapper in the form of std::function seems to be the go-to answer, despite the increased size of the resulting function-object.
Possible alternatives might be storing Functor objects designed to mimic closures couples with generic objects with a type-checking layer (though this seems quite heavy). Whatever the case, using std::function seems to be the cleanest solution.
How about this?
#include <iostream>
#include <functional>
#include <vector>
int add(int a, int b) { return a + b; }
using bound_add_t = decltype(std::bind(add, std::placeholders::_1, int()));
int main() {
std::vector<bound_add_t> vec;
vec.emplace_back(add,std::placeholders::_1, 1);
vec.emplace_back(add,std::placeholders::_1, 2);
vec.emplace_back(add,std::placeholders::_1, 3);
for (auto &b : vec)
std::cout << b(5) << std::endl;
return 0;
}
Thanks for giving comments to the following.
Class1 { debug(std::ostream&){} };
int main() {
std::vector<Class1*> list1;
// some work to do
}
Target Platform:
Platform(1): Win 7x64, VS2010
Platform(2): Linux x32, g++ 4.4
Q: What should be the correct way to pass "std::cout" to following statement?
std::for_each(list1.begin(),
list1.end(),
"afunction(&Class1::debug, std::cout)");
I previously used "std::cout" inside the debug() function, but later consider to give flexibility for the output of debug message.
Edit: More information: if functor objects is the way to go, how should I implements the functor to cope with multiple classes (those classes have no relationship except the same "debug" function signature)?
Edit(2): Using "std::for_each", is it possible to destroy all objects in list1 by invoking the corresponding destructor for each class directly? (e.g. for_each(l.begin(), l.end(), "Class::~Class1");
Edit(3): As per "pmr" suggested, I make the statement as
std::for_each(l.begin(),
l.end(),
std::bind2nd(std::mem_fn(&Class1::debug), out) );
It compiles and run correctly on linux platform, but failed on VS2010, the code for Class1::debug is
void Class1::debug(const std::ostream& out)
{
out << "some text" << someVar << "some text" << std::endl;
}
The VS error msg is
error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'const std::ostream' (or there is no acceptable conversion)
Any cue?
[Closed]
I now implemented the overloaded operator << for my classes, and the use of debug print function is closed. Thanks very much for all hints given.
Since you are using g++ 4.4 you can't use lambda expressions which would be the first choice (later versions support them, MSVC does as well).
So you need a functor. A functor is a function object, that is a class (or struct) that implements operator(). Like this:
class Debug
{
public:
Debug(ostream& os) : _os(os)
{ }
void operator()(Class1* instance)
{
// will print the pointer, replace with user code
os << instance << endl;
}
private:
ostream& _os;
};
Use like this:
Debug d(cout);
std::for_each(list1.begin(), list1.end(), d);
use lambda instead of function pointers. This is a feature of C++11x and you need to include a flag for compiler to recognise lambda.
std::for_each(list1.begin(), list1.end(), [&debug, &cout]
{
// implementaion
}
);
As GCC does not support lambdas until 4.5, the clearest solution is out of the question.
The second easiest solution when you want to use a lot of generic algorithms is Boost.Lambda http://www.boost.org/doc/libs/1_49_0/doc/html/lambda.html:
for_each(list1.begin(), list.end(), _1->debug(cout));
And finally, the tedious functor solution:
class Output
{
public:
explicit Output(ostream& ios) : os(&ios)
{
}
void operator()(Class1* obj)
{
obj->debug(*os);
}
private:
ostream* os;
};
for_each(list1.begin(), list1.end(), Output(cout));
Personally I think that without C++11 lambdas or Boost Lambdas, for_each is more pain than it's worth. Might as well do a simple loop:
for (vector<Class1*>::iterator it = list1.begin(); it != end; ++it)
(*it)->debug(cout);
C++03:
#include <vector>
#include <functional>
#include <iostream>
#include <algorithm>
struct Foo {
void debug(std::ostream&) {}
};
int main()
{
std::vector<Foo*> foos;
std::for_each(foos.begin(), foos.end(),
std::bind2nd(std::mem_fun(&Foo::debug), std::cout));
return 0;
}
Please note that the binders have been deprecated and boost::bind or
C++11 should be favored. You should really get a newer compiler.
boost::filesystem::recursive_directory_iterator end, begin(directory);
auto num_of_files=std::count_if(begin, end,
std::not1(boost::filesystem::is_directory)));
I am trying to negate the function is_directory on the above directory iterator but am hitting a brick wall. I have tried specifying the template for not1 as bool(*)(const boost::filesystem::path&) and tried static casting the function both without success.
I know I can resort to a lamdba but this is cleaner if it works.
Thanks
std::not1 needs a function object as its argument. This function object can be obtained with std::ptr_fun, so this should work:
auto num_of_files=std::count_if(begin, end,
std::not1(std::ptr_fun((bool(*)(const boost::filesystem::path&))boost::filesystem::is_directory)));
(the number of parentheses is probably incorrect). BTW, you need the cast because is_directory is an overloaded function.
However, since you tag you question c++11, you could use lambdas:
auto num_of_files=std::count_if(begin, end, [](const boost::filesystem::path& p) { return !boost::filesystem::is_directory(p); });
not1 accepts an instance of functor class, which should be an Adaptable Predicate (i.e. with typedefs for return value etc.), while you are trying to feed it with a function pointer. So you need to wrap it in a functor and ptr_fun might help.
Perhaps this would work (assume using namespace std; using namespace boost;):
auto num_of_files=count_if(begin, end, not1(ptr_fun(filesystem::is_directory)));
You need ptr_fun,
this rather elaborate illustration should print 1 three times: (see also http://ideone.com/C5HTR)
#include <functional>
#include <string>
#include <algorithm>
#include <iostream>
bool pred(const std::string& s)
{
return s.size() % 2;
}
int main()
{
std::string data[] = { "hello", "world!" };
std::cout << std::count_if(data, data+2,
pred) << std::endl;
std::cout << std::count_if(data, data+2,
std::ptr_fun(pred) ) << std::endl;
std::cout << std::count_if(data, data+2,
std::not1(std::ptr_fun(pred))) << std::endl;
return 0;
}