views:

140

answers:

1

Hi, I have some complex types here so I decided to use nifty trick to have typedef on templated types. Then I have a class some_container that has a container as a member. Container is a vector of pairs composed of element and vector. I want to write std::find_if algorithm with lambda expression to find element that have certain value. To get the value I have to call first on pair and then get value from element. Below my std::find_if there is normal loop that does the trick. My lambda fails to compile. How to access value inside element which is inside pair? I use g++ 4.4+ and VS 2010 and I want to stick to boost lambda for now.

#include <vector>
#include <algorithm>
#include <boost\lambda\lambda.hpp>
#include <boost\lambda\bind.hpp>

template<typename T>
class element
{
public:
   T value;
};

template<typename T>
class element_vector_pair // idiom to have templated typedef
{
public:
   typedef std::pair<element<T>, std::vector<T> > type;
};

template<typename T>
class vector_containter // idiom to have templated typedef
{
public:
   typedef std::vector<typename element_vector_pair<T>::type > type;
};

template<typename T>
bool operator==(const typename element_vector_pair<T>::type & lhs, const typename element_vector_pair<T>::type & rhs)
{
   return lhs.first.value == rhs.first.value;
}

template<typename T>
class some_container
{
public:
   element<T> get_element(const T& value) const
   {
      std::find_if(container.begin(), container.end(), bind(&typename vector_containter<T>::type::value_type::first::value, boost::lambda::_1) == value);
      /*for(size_t i = 0; i < container.size(); ++i)
      {
      if(container.at(i).first.value == value)
      {
      return container.at(i);
      }
      }*/
      return element<T>(); //whatever
   }

protected:
   typename vector_containter<T>::type container;
};

int main()
{
   some_container<int> s;
   s.get_element(5);
   return 0;
}
+1  A: 

Two issues.

The thing that you are going after (element<T>::value) is not a typename.

However, firstly you'll need nested binds: one to access _1.first and another one to access the value of the previous.

Without the typedefs:

  std::find_if(
    container.begin(), container.end(),
    bind(
      &element<T>::value,
      bind(&std::pair<element<T>, std::vector<T> >::first, boost::lambda::_1)
    ) == value
  ); 

And so, with your idiom, without the unnecessary typename:

  std::find_if( container.begin(), container.end(),
    bind(
      &vector_containter<T>::type::value_type::first_type::value,
      bind(
         &vector_containter<T>::type::value_type::first, boost::lambda::_1)
      ) == value
  );

This doesn't seem particularly readable, though. Perhaps a) wait for C++0x lambda, b) write a specific functor for the find_if call, c) just do a manual loop.

UncleBens