문제

나는 2 년 동안 많은 C#과 최근에 C#을 수행 한 후 C ++로 돌아오고 있습니다.

내가 전에 한 한 가지는 Key-Value 쌍보다는 값 부분으로 Deref를 deref로하는 std :: map의 내 반복자 어댑터를 굴리는 것입니다. 이것은 매우 일반적이고 자연스러운 일입니다. C#은이 시설에 사전 클래스의 키와 가치 속성을 제공합니다. Objective-C의 nsdictionary는 마찬가지로 Allkeys와 AllValues를 가지고 있습니다.

내가 "멀리"지 낸 이후로 Boost는 범위와 Foreach Libraries를 획득했으며 현재 광범위하게 사용하고 있습니다. 나는 둘 사이에 똑같이 할 시설이 있는지 궁금했지만 아무것도 찾을 수 없었습니다.

나는 Boost의 반복자 어댑터를 사용하여 무언가를 두드릴 생각을하고 있지만, 그 경로를 내려 가기 전에 Boost의 그러한 시설을 알고 있는지 또는 다른 곳에서 준비된 다른 곳에서 물어볼 것이라고 생각 했습니까?

도움이 되었습니까?

해결책

나는 상자 밖에 아무것도 없다고 생각합니다. boost :: make_transform을 사용할 수 있습니다.

template<typename T1, typename T2> T2& take_second(const std::pair<T1, T2> &a_pair) 
{
  return a_pair.second;
}

void run_map_value()
{
  map<int,string> a_map;
  a_map[0] = "zero";
  a_map[1] = "one";
  a_map[2] = "two";
  copy( boost::make_transform_iterator(a_map.begin(), take_second<int, string>),
    boost::make_transform_iterator(a_map.end(), take_second<int, string>),
    ostream_iterator<string>(cout, "\n")
    );
}

다른 팁

다른 사람이 내가 한 것처럼 이것을 찾을 경우 이전 답변을 대체합니다. Boost 1.43 기준으로 일반적으로 사용되는 범위 어댑터가 제공됩니다. 이 경우 부스트 :: 어댑터 :: map_values를 원합니다. 관련 예 :http://www.boost.org/doc/libs/1_46_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html#range.reference.adaptors.reference.map_values.map_values_examplice

이 목적을위한 부스트 범위 어댑터가 있습니다. 보다 http://www.boost.org/doc/libs/1_53_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html

(이 예제는 거기에서 젖 힙니다)

int main(int argc, const char* argv[])
{
    using namespace boost::assign;
    using namespace boost::adaptors;

    std::map<int,int> input;
    for (int i = 0; i < 10; ++i)
    input.insert(std::make_pair(i, i * 10));

    boost::copy(
        input | map_values,
        std::ostream_iterator<int>(std::cout, ","));

    return 0;
}

David의 대답을 계속하면 Boost :: Transform_iterator에서 파생 된 클래스를 만들어 Boile을 배치 할 수있는 또 다른 가능성이 있습니다. 프로젝트 에서이 솔루션을 사용하고 있습니다.

namespace detail
{

template<bool IsConst, bool IsVolatile, typename T>
struct add_cv_if_c
{
    typedef T type;
};
template<typename T>
struct add_cv_if_c<true, false, T>
{
    typedef const T type;
};
template<typename T>
struct add_cv_if_c<false, true, T>
{
    typedef volatile T type;
};
template<typename T>
struct add_cv_if_c<true, true, T>
{
    typedef const volatile T type;
};

template<typename TestConst, typename TestVolatile, typename T>
struct add_cv_if: public add_cv_if_c<TestConst::value, TestVolatile::value, T>
{};

}   // namespace detail


/** An unary function that accesses the member of class T specified in the MemberPtr template parameter.

    The cv-qualification of T is preserved for MemberType
 */
template<typename T, typename MemberType, MemberType T::*MemberPtr>
struct access_member_f
{
    // preserve cv-qualification of T for T::second_type
    typedef typename detail::add_cv_if<
        std::tr1::is_const<T>, 
        std::tr1::is_volatile<T>, 
        MemberType
    >::type& result_type;

    result_type operator ()(T& t) const
    {
        return t.*MemberPtr;
    }
};

/** @short  An iterator adaptor accessing the member called 'second' of the class the 
    iterator is pointing to.
 */
template<typename Iterator>
class accessing_second_iterator: public 
    boost::transform_iterator<
        access_member_f<
            // note: we use the Iterator's reference because this type 
            // is the cv-qualified iterated type (as opposed to value_type).
            // We want to preserve the cv-qualification because the iterator 
            // might be a const_iterator e.g. iterating a const 
            // std::pair<> but std::pair<>::second_type isn't automatically 
            // const just because the pair is const - access_member_f is 
            // preserving the cv-qualification, otherwise compiler errors will 
            // be the result
            typename std::tr1::remove_reference<
                typename std::iterator_traits<Iterator>::reference
            >::type, 
            typename std::iterator_traits<Iterator>::value_type::second_type, 
            &std::iterator_traits<Iterator>::value_type::second
        >, 
        Iterator
    >
{
    typedef boost::transform_iterator<
        access_member_f<
            typename std::tr1::remove_reference<
                typename std::iterator_traits<Iterator>::reference
            >::type, 
            typename std::iterator_traits<Iterator>::value_type::second_type, 
            &std::iterator_traits<Iterator>::value_type::second
        >, 
        Iterator
    > baseclass;

public:
    accessing_second_iterator(): 
        baseclass()
    {}

    // note: allow implicit conversion from Iterator
    accessing_second_iterator(Iterator it): 
        baseclass(it)
    {}
};

이것은 더 깨끗한 코드로 이어집니다.

void run_map_value()
{
  typedef map<int, string> a_map_t;
  a_map_t a_map;
  a_map[0] = "zero";
  a_map[1] = "one";
  a_map[2] = "two";

  typedef accessing_second_iterator<a_map_t::const_iterator> ia_t;
  // note: specify the iterator adaptor type explicitly as template type, enabling 
  // implicit conversion from begin()/end()
  copy<ia_t>(a_map.begin(), a_map.end(),
    ostream_iterator<string>(cout, "\n")
  );
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top