Range-based for with brace-initializer over non-const values? - c++

I am trying to iterate over a number of std::lists, sorting each of them. This is the naive approach:
#include<list>
using namespace std;
int main(void){
list<int> a,b,c;
for(auto& l:{a,b,c}) l.sort();
}
producing
aa.cpp:5:25: error: no matching member function for call to 'sort'
for(auto& l:{a,b,c}) l.sort();
~~^~~~
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1586:7: note:
candidate function not viable: 'this' argument has type 'const
std::list<int, std::allocator<int> >', but method is not marked const
sort();
^
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1596:9: note:
candidate function template not viable: requires 1 argument, but 0 were
provided
sort(_StrictWeakOrdering);
^
1 error generated.
Am I correctly guessing that brace-initializer is creating copy of those lists? And is there a way to not copy them, and make them modifiable inside the loop? (other than making list of pointers to them, which is my current workaround).

You are guessing correctly. std::initializer_list elements are always const (which makes sort()ing them impossible, as sort() is a non-const member function) and its elements are always copied (which would make sort()-ing them meaningless even if they weren't const). From [dcl.init.list], emphasis mine:
An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation
allocated a temporary array of N elements of type const E, where N is the number of elements in the
initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer
list, and the std::initializer_list<E> object is constructed to refer to that array. [ Note: A constructor
or conversion function selected for the copy shall be accessible (Clause 11) in the context of the initializer
list. —end note ] If a narrowing conversion is required to initialize any of the elements, the program is
ill-formed. [ Example:
struct X {
X(std::initializer_list<double> v);
};
X x{ 1,2,3 };
The initialization will be implemented in a way roughly equivalent to this:
const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));
assuming that the implementation can construct an initializer_list object with a pair of pointers. —end
example ]
There is no way to make them non-const or non-copied. The pointer solution works:
for (auto l : {&a, &b, &c}) l->sort();
because it's the pointer that's const, not the element it's pointing to. The other alternative would be to write a variadic function template:
template <typename... Lists>
void sortAll(Lists&&... lists) {
// before C++17
using expander = int[];
expander{0, (void(lists.sort()), 0)...};
// C++17 or later
(lists.sort(), ...);
}
sortAll(a, b, c);
You could also, I guess, write a helper to wrap your lists into an array of reference_wrapper to list<int> (since you can't have an array of references), but this is probably more confusing than helpful:
template <typename List, typename... Lists>
std::array<std::reference_wrapper<List>, sizeof...(Lists) + 1>
as_array(List& x, Lists&... xs) {
return {x, xs...};
}
for (list<int>& l : as_array(a, b, c)) { // can't use auto, that deduces
l.sort(); // reference_wrapper<list<int>>,
} // so would need l.get().sort()

It is possible to write a function ref_range which allows you to do this:
for(auto& l : ref_range(a,b,c)) {
l.sort();
}
As others have said, once you write {a,b,c} you are stuck with an initializer_list, and such a list always takes copies of its arguments. The copies are const (hence your error), but even if you could get a non-const reference you would be modifying the copies of a, b and c instead of the originals.
Anyway, here is ref_range. It builds a vector of reference_wrapper.
// http://stackoverflow.com/questions/31724863/range-based-for-with-brace-initializer-over-non-const-values
#include<list>
#include<functional>
#include<array>
template<typename T, std:: size_t N>
struct hold_array_of_refs {
using vec_type = std:: array< std:: reference_wrapper<T>, N >;
vec_type m_v_of_refs;
hold_array_of_refs(vec_type && v_of_refs) : m_v_of_refs(std::move(v_of_refs)) { }
~hold_array_of_refs() { }
struct iterator {
typename vec_type :: const_iterator m_it;
iterator(typename vec_type :: const_iterator it) : m_it(it) {}
bool operator != (const iterator &other) {
return this->m_it != other.m_it;
}
iterator& operator++() { // prefix
++ this->m_it;
return *this;
}
T& operator*() {
return *m_it;
}
};
iterator begin() const {
return iterator(m_v_of_refs.begin());
}
iterator end() const {
return iterator(m_v_of_refs.end());
}
};
template<typename... Ts>
using getFirstTypeOfPack = typename std::tuple_element<0, std::tuple<Ts...>>::type;
template<typename ...T>
auto ref_range(T&... args) -> hold_array_of_refs< getFirstTypeOfPack<T...> , sizeof...(args)> {
return {{{ std:: ref(args)... }}}; // Why does clang prefer three levels of {} ?
}
#include<iostream>
int main(void){
std:: list<int> a,b,c;
// print the addresses, so we can verify we're dealing
// with the same objects
std:: cout << &a << std:: endl;
std:: cout << &b << std:: endl;
std:: cout << &c << std:: endl;
for(auto& l : ref_range(a,b,c)) {
std:: cout << &l << std:: endl;
l.sort();
}
}

The {...} syntax is actually creating an std::initializer_list. As the linked page states :
A std::initializer_list object is automatically constructed when:
[...]
a braced-init-list is bound to auto, including in a ranged for loop
And :
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T.
Thus, you can't modify the objects accessed through this initialize_list. Your solutions with the pointers looks like the easiest one to me.

Direct answer to your question:
Am I correctly guessing that brace-initializer is creating copy of
those lists?
Yes, this is the first problem. Your code would create copies of your lists, sort those copies, and finally forget the sorted copies.
However, that alone would just result in non-working code. The compiler error hints to a second problem: The implicit type of l is list<int> const&, rather than list<int>&. So the compiler complains that sort() tries to modify constant lists.
You can work around this second problem with a nasty const_cast:
#include <list>
#include <iostream>
using namespace std;
int main(void){
list<int> a,b,c;
a.push_back(2);
a.push_back(0);
a.push_back(1);
for(auto& l:{a,b,c}) const_cast<list<int>&>(l).sort();
for(auto i:a) cout << i << endl;
}
However, that will then trigger the first problem: Your list of lists contains copies, and only those copies are sorted. So the final output is not what you want:
2
0
1
The easiest workaround is to create a list of pointers to your lists:
#include <list>
#include <iostream>
using namespace std;
int main(void){
list<int> a,b,c;
a.push_back(2);
a.push_back(0);
a.push_back(1);
for(auto l:{&a,&b,&c}) l->sort();
for(auto i:a) cout << i << endl;
}
This will produce the desired result:
0
1
2

Others have already mentioned std::reference_wrapper, but they then used it to create an STL container instead of sticking with the brace-initializer list.
So all you need to do is:
for(auto& l:{std::ref(a),std::ref(b),std::ref(c)}) l.get().sort();
Of course, this is very similiar to the pointer solution already suggested.

Related

How do I iterate over a group of vectors by their references? [duplicate]

I am trying to iterate over a number of std::lists, sorting each of them. This is the naive approach:
#include<list>
using namespace std;
int main(void){
list<int> a,b,c;
for(auto& l:{a,b,c}) l.sort();
}
producing
aa.cpp:5:25: error: no matching member function for call to 'sort'
for(auto& l:{a,b,c}) l.sort();
~~^~~~
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1586:7: note:
candidate function not viable: 'this' argument has type 'const
std::list<int, std::allocator<int> >', but method is not marked const
sort();
^
/usr/bin/../lib64/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_list.h:1596:9: note:
candidate function template not viable: requires 1 argument, but 0 were
provided
sort(_StrictWeakOrdering);
^
1 error generated.
Am I correctly guessing that brace-initializer is creating copy of those lists? And is there a way to not copy them, and make them modifiable inside the loop? (other than making list of pointers to them, which is my current workaround).
You are guessing correctly. std::initializer_list elements are always const (which makes sort()ing them impossible, as sort() is a non-const member function) and its elements are always copied (which would make sort()-ing them meaningless even if they weren't const). From [dcl.init.list], emphasis mine:
An object of type std::initializer_list<E> is constructed from an initializer list as if the implementation
allocated a temporary array of N elements of type const E, where N is the number of elements in the
initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer
list, and the std::initializer_list<E> object is constructed to refer to that array. [ Note: A constructor
or conversion function selected for the copy shall be accessible (Clause 11) in the context of the initializer
list. —end note ] If a narrowing conversion is required to initialize any of the elements, the program is
ill-formed. [ Example:
struct X {
X(std::initializer_list<double> v);
};
X x{ 1,2,3 };
The initialization will be implemented in a way roughly equivalent to this:
const double __a[3] = {double{1}, double{2}, double{3}};
X x(std::initializer_list<double>(__a, __a+3));
assuming that the implementation can construct an initializer_list object with a pair of pointers. —end
example ]
There is no way to make them non-const or non-copied. The pointer solution works:
for (auto l : {&a, &b, &c}) l->sort();
because it's the pointer that's const, not the element it's pointing to. The other alternative would be to write a variadic function template:
template <typename... Lists>
void sortAll(Lists&&... lists) {
// before C++17
using expander = int[];
expander{0, (void(lists.sort()), 0)...};
// C++17 or later
(lists.sort(), ...);
}
sortAll(a, b, c);
You could also, I guess, write a helper to wrap your lists into an array of reference_wrapper to list<int> (since you can't have an array of references), but this is probably more confusing than helpful:
template <typename List, typename... Lists>
std::array<std::reference_wrapper<List>, sizeof...(Lists) + 1>
as_array(List& x, Lists&... xs) {
return {x, xs...};
}
for (list<int>& l : as_array(a, b, c)) { // can't use auto, that deduces
l.sort(); // reference_wrapper<list<int>>,
} // so would need l.get().sort()
It is possible to write a function ref_range which allows you to do this:
for(auto& l : ref_range(a,b,c)) {
l.sort();
}
As others have said, once you write {a,b,c} you are stuck with an initializer_list, and such a list always takes copies of its arguments. The copies are const (hence your error), but even if you could get a non-const reference you would be modifying the copies of a, b and c instead of the originals.
Anyway, here is ref_range. It builds a vector of reference_wrapper.
// http://stackoverflow.com/questions/31724863/range-based-for-with-brace-initializer-over-non-const-values
#include<list>
#include<functional>
#include<array>
template<typename T, std:: size_t N>
struct hold_array_of_refs {
using vec_type = std:: array< std:: reference_wrapper<T>, N >;
vec_type m_v_of_refs;
hold_array_of_refs(vec_type && v_of_refs) : m_v_of_refs(std::move(v_of_refs)) { }
~hold_array_of_refs() { }
struct iterator {
typename vec_type :: const_iterator m_it;
iterator(typename vec_type :: const_iterator it) : m_it(it) {}
bool operator != (const iterator &other) {
return this->m_it != other.m_it;
}
iterator& operator++() { // prefix
++ this->m_it;
return *this;
}
T& operator*() {
return *m_it;
}
};
iterator begin() const {
return iterator(m_v_of_refs.begin());
}
iterator end() const {
return iterator(m_v_of_refs.end());
}
};
template<typename... Ts>
using getFirstTypeOfPack = typename std::tuple_element<0, std::tuple<Ts...>>::type;
template<typename ...T>
auto ref_range(T&... args) -> hold_array_of_refs< getFirstTypeOfPack<T...> , sizeof...(args)> {
return {{{ std:: ref(args)... }}}; // Why does clang prefer three levels of {} ?
}
#include<iostream>
int main(void){
std:: list<int> a,b,c;
// print the addresses, so we can verify we're dealing
// with the same objects
std:: cout << &a << std:: endl;
std:: cout << &b << std:: endl;
std:: cout << &c << std:: endl;
for(auto& l : ref_range(a,b,c)) {
std:: cout << &l << std:: endl;
l.sort();
}
}
The {...} syntax is actually creating an std::initializer_list. As the linked page states :
A std::initializer_list object is automatically constructed when:
[...]
a braced-init-list is bound to auto, including in a ranged for loop
And :
An object of type std::initializer_list<T> is a lightweight proxy object that provides access to an array of objects of type const T.
Thus, you can't modify the objects accessed through this initialize_list. Your solutions with the pointers looks like the easiest one to me.
Direct answer to your question:
Am I correctly guessing that brace-initializer is creating copy of
those lists?
Yes, this is the first problem. Your code would create copies of your lists, sort those copies, and finally forget the sorted copies.
However, that alone would just result in non-working code. The compiler error hints to a second problem: The implicit type of l is list<int> const&, rather than list<int>&. So the compiler complains that sort() tries to modify constant lists.
You can work around this second problem with a nasty const_cast:
#include <list>
#include <iostream>
using namespace std;
int main(void){
list<int> a,b,c;
a.push_back(2);
a.push_back(0);
a.push_back(1);
for(auto& l:{a,b,c}) const_cast<list<int>&>(l).sort();
for(auto i:a) cout << i << endl;
}
However, that will then trigger the first problem: Your list of lists contains copies, and only those copies are sorted. So the final output is not what you want:
2
0
1
The easiest workaround is to create a list of pointers to your lists:
#include <list>
#include <iostream>
using namespace std;
int main(void){
list<int> a,b,c;
a.push_back(2);
a.push_back(0);
a.push_back(1);
for(auto l:{&a,&b,&c}) l->sort();
for(auto i:a) cout << i << endl;
}
This will produce the desired result:
0
1
2
Others have already mentioned std::reference_wrapper, but they then used it to create an STL container instead of sticking with the brace-initializer list.
So all you need to do is:
for(auto& l:{std::ref(a),std::ref(b),std::ref(c)}) l.get().sort();
Of course, this is very similiar to the pointer solution already suggested.

how to decide if bind() need parenthesis in the parameter

I am using bind() to bind a function and its parameters together. I used the build-in functor multiplies and I also tried a function I wrote myself AddVal2(). The following is a correct version of the code. But I really don't understand why std::bind(std::multiplies<int>(),std::placeholders::_1,10) has to include () with multiplies<int>, while bind(AddVal2,std::placeholders::_1,10) write AddVal2 instead of AddVal2(). Thank you.
#include<iostream>
#include<vector>
#include<algorithm>
void AddVal2(int x, int y)
{ std::cout << x+y << std::endl;}
int main()
{
std::vector<int> vec = {1,2,3,4,5};
std::vector<int> vec_result;
std::transform(vec.begin(),vec.begin()+2,std::back_inserter(vec_result),std::bind(std::multiplies<int>(),std::placeholders::_1,10));
for (std::vector<int>::iterator itr = vec_result.begin(); itr !=vec_result.end();++itr){std::cout << *itr << std::endl;}
for_each(vec.begin(),vec.end(),std::bind(AddVal2,std::placeholders::_1,10));
}
That's simple: std::multiplies<T> is a class template which defines a
function call operator. It looks something like this:
template <typename T>
struct multiplies {
// some typedefs are here, too
T operator()(T const& a0, T const& a1) const { return a0 * a1; }
};
To create such an object, you'll use a default constructor, i.e., std::multiplies<T>().
On the other hand AddVal2 is a function. To get a function object from a normal function you just mention the function and it'll decay into a function pointer. Alternatively you can also use &AddVal2 to explicitly obtain a function pointer (for member functions you have to explicitly take the address).

Do gcc and clang STL implementations violate rules about allocator?

In 23.2.1p3 C++11 Standart we can read:
For the components affected by this subclause that declare an allocator_type, objects stored in these components shall be constructed using the allocator_traits<allocator_type>::construct function and destroyed using the allocator_traits<allocator_type>::destroy function (20.6.8.2). These functions are called only for the container’s element type, not for internal types used by the container. [ Note: This means, for example, that a node-based container might need to construct nodes containing aligned buffers and call construct to place the element into the buffer. —end note ]
allocator_traits<allocator_type>::construct just call passed allocator's construct method, if allocator defines one. I tried to use this and create allocator, which use list-initialization for construction, so I can utilize emplace for aggregate initialization:
#include <memory>
#include <vector>
#include <string>
#include <iostream>
#include <cmath>
template<typename T>
struct init_list_allocator : public std::allocator<T> {
template<typename... Args>
void construct(T* p, Args&&... args)
{ ::new((void *)p) T{std::forward<Args>(args)...}; }
// Fix copy-constructors usage for aggregates
void construct(T* p, T& copy_construct_arg)
{ std::allocator<T>::construct(p, copy_construct_arg); }
void construct(T* p, const T& copy_construct_arg)
{ std::allocator<T>::construct(p, copy_construct_arg); }
void construct(T* p, const T&& copy_construct_arg)
{ std::allocator<T>::construct(p, std::move(copy_construct_arg)); }
void construct(T *p, T&& move_construct_arg)
{ std::allocator<T>::construct(p, std::move(move_construct_arg)); }
};
template<class T>
using improved_vector = std::vector<T, init_list_allocator<T>>;
struct A {
int x;
double y;
const char* z;
};
int main()
{
using namespace std;
vector<string> strings;
improved_vector<A> v;
for (int i = 0; i < 21; ++i) {
strings.emplace_back(to_string(i*i));
v.emplace_back(i, sqrt(i), strings.back().c_str());
};
for (const auto& elem : v)
cout << elem.x << ' ' << elem.y << ' ' << elem.z << '\n';
}
However, at least in gcc and clang, this doesn't work. The problem is, that their implementations of vector use Allocator::rebind<T>::other::construct instead of Allocator::construct. And, because of our inheritance from std::allocator, this rebind gives std::allocator<T>::construct. Ok, no problem, just add
template<typename U>
struct rebind {
using other = init_list_allocator<U>;
};
in our allocator's definition and this code will work. Great, now let's change vector to list. Here we have the unsolvable problem, because instead of Allocator::construct object is initialized inside std::_List_node<_Tp> constuctor in direct-initialization form (form with brackets).
Are this 2 issues a standard violations or I miss something?
To my understanding, libstdc++ and MSVC++ are correct here. The point of rebind is, as the note indicates, that containers may be required to construct things that are not T. For example, std::list<T> needs to construct a list node containing T, not T. Similar cases exist for the associative and unordered containers. That's why the rebind structure exists in the first place. Your allocator was nonconforming before that was in place.
For the second issue, your reference
These functions are called only for the container’s element type, not for internal types used by the container.
seems to indicate that standard library implementations aren't allowed to call construct for rebound allocators, however. This may be a bug in libstdc++.
As for the actual solution to this problem, give A a constructor that has the behavior you want, and don't bother with allocators for this purpose. People may want to create instances of A outside of a container with the special allocator:
#include <vector>
struct A {
int x;
double y;
const char* z;
A() = default; // This allows A to still be a POD because the default constructor
// is not "user-provided", see 8.4.2 [dcl.fct.def.default]/4
A(int x_, double y_, char const* z_) : x(x_), y(y_), z(z_) {}
};
int main()
{
using namespace std;
vector<string> strings;
vector<A> v;
for (int i = 0; i < 21; ++i) {
strings.emplace_back(to_string(i*i));
v.emplace_back(i, sqrt(i), strings.back().c_str());
};
for (const auto& elem : v)
cout << elem.x << ' ' << elem.y << ' ' << elem.z << '\n';
}
After some research, I have found the answer myself and want to provide it.
For the first issue (using Allocator::rebind<T>::other::construct instead of Allocator::construct), my first allocator implementation (second one is OK) doesn't satisfy Allocator requirements in part of rebind, see 17.6.3.5 Table 28:
+------------------+-------------+-------------------------------------+
| Expression | Return type | Assertion/note pre-/post- condition |
+------------------+-------------+-------------------------------------+
| typename | Y | For all U (including T), |
| X::template | | Y::template rebind<T>::other is X. |
| rebind<U>::other | | |
+------------------+-------------+-------------------------------------+
For the second issue: GCC has old, pre-C++11 implementation of std::list, which will be fixed only in GCC 5.0, because this change breaks ABI (see Should std::list::size have constant complexity in C++11? for more info)
However, the quoted standard requirement, that container must call construct function for exactly allocator_type and not for some rebinded type seems like a standard defect (http://cplusplus.github.io/LWG/lwg-active.html#2218). Libstdc++ implementations of std::set, multiset, map and multimap rely on this fact and use rebinded allocator for construct (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64096).

How to store either rvalue or lvalue references in template

I am trying to create a simple template enumerator class that should accept any object over which : operator is defined and later on print pairs of the form (i, v[i]). A simple implementation is the following:
template<typename T>
struct enumerator {
T &v; // reference to minimize copying
enumerator(T &_v) : v(_v) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
This works ok for things like:
Case A
vector<int> v({1,2,6,2,4});
auto e = enumerator(v);
e.do_enumerate();
However, I would also like it to handle temporary objects like:
Case B
auto e = enumerator(vector<int>({2,3,9});
e.do_enumerate();
This does not work and the compiler throws:
no matching function for call to ‘enumerator<std::vector<int> >::enumerator(std::vector<int>)
So, I tried to then add a
enumerator(T _t) : t(_T) {}
constructor to resolve this error. Now case A does not work and there is an error:
error: call of overloaded ‘enumerator(std::vector<int>&)’ is ambiguous
Moreover, in case B, the output of the enumeration is not correct.
What is the cleanest way to solve this? I would
really like both cases to be working
prefer not to use any libraries other than stdc++
want as little copying as possible (thus just storing a T t in the struct is not an option)
C++11 is not a problem. I have g++-4.8, which I presume has complete enough C++11 support.
Well I would like to copy in case the argument is an rvalue, and not copy in case it is not. Is that possible?
This can be accomplished using a make_enumerator helper function as shown.
template <class T>
struct enumerator {
T v;
enumerator(T&& _v) : v(std::forward<T>(_v)) {}
void do_enumerate() {
size_t i = 0;
for(auto x : v) {
cout << i << x << endl;
i++;
}
}
};
template <class T>
enumerator<T> make_enumerator(T&& x) {
return enumerator<T>(std::forward<T>(x));
}
int main() {
vector<int> v {5, 2, 9, 1};
make_enumerator(v).do_enumerate();
make_enumerator(std::move(v)).do_enumerate();
}
How does this work?
If the argument to make_enumerator is an lvalue of type A then T is deduced as A& and we get the enumerator enumerator<A&>, whereas if it is an rvalue of type A then T is deduced as A and we get the enumerator enumerator<A>.
In the first case the member enumerator::v will have type A&, an lvalue reference that binds to the constructor argument (no copying). In the second case the member will have type A. The use of std::forward casts the parameter _v to an rvalue, so it will be moved from when it is used to initialize v.
This is a classic example where you don't actually need a class/struct (which actually introduce useless code) and you can just use good old functions:
template<typename Container>
void enumerate(const Container& t) {
std::size_t i = 0;
for(auto it = t.begin(); it != t.end(); ++it, ++i)
std::cout << i << *it << std::endl;
}
and then call it as:
enumerate(std::vector<int>{2,3,9});
Live demo
With this method you also get argument type inference for free (which you don't get with a struct).

How can I search a container of objects for a data member value?

I have an object type like this:
struct T
{
int x;
bool y;
};
and a container of them like this:
std::vector<T> v;
and a burning desire to determine — in a single statement — whether any of the elements of v have y == true. This likely involves std::find_if.
My understanding is that std::bind and boost::bind are for member functions and cannot be applied to member data.
Because I dislike them, I wish to avoid:
comparison functions/functors
loops
Because my environment is C++03, the following are not available:
lambdas
My understanding is that std::bind and boost::bind are for member functions and cannot be applied to member data.
Remarkably, this is not the case! boost::bind will happily bind to member data and allow you to perform operations on it during an "inline iteration".
From the documentation:
Pointers to member functions and pointers to data members are not function objects, because they do not support operator(). For convenience, bind accepts member pointers as its first argument, and the behavior is as if boost::mem_fn has been used to convert the member pointer into a function object. In other words, the expression
bind(&X::f, args)
is equivalent to
bind<R>(mem_fn(&X::f), args)
where R is the return type of X::f (for member functions) or the type of the member (for data members.)
Also, from the documentation for boost::mem_fn:
mem_fn also supports pointers to data members by treating them as functions taking no arguments and returning a (const) reference to the member.
So, you can do this:
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <boost/bind.hpp>
struct T
{
int x;
bool y;
};
void f(const std::string& name, const std::vector<T>& v)
{
const bool found = std::find_if(
v.begin(),
v.end(),
boost::bind(&T::y, _1) == true
) != v.end();
std::cout << name << ": " << (found ? " FOUND" : " not found") << '\n';
}
int main()
{
T a = { 0, false };
T b = { 1, false };
T c = { 2, true };
std::vector<T> v;
f("a", v);
v.push_back(a);
v.push_back(b);
f("b", v);
v.push_back(c);
f("c", v);
}
Output:
a: not found
b: not found
c: FOUND
What you want (to determine — in a single statement — whether any of the elements of v have y == true) seems to be:
inline bool y_is_true(std::vector<T>::iterator i) { return i->y; };
(outside your function) and
bool found = std::find_if(v.begin(), v.end(), y_is_true) != v.end();
Another option is to use boost::lambda:
bool found = std::find_if(v.begin(), v.end(), _1.y) != v.end();