1

私は一般的な方法で group_by メソッドを実装して遊んでいましたが、おそらくそれを実装しました(C配列では機能しないことを除いて)が、それでもコードは私には醜く見えます...

私が望むことを行うためのより簡単な方法はありますか(+すべてのコンテナとC配列で機能するようにするには(C配列(TT)で機能させる方法がわかりません)?
それが明らかでない場合は、stdの型について話している::multimap... ところで、C++14 ではこれを 2 回入力する必要がなくなることはわかっています ( auto は、後で書き込むタイプを認識します -> )

// group_by.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include <map>
#include <deque>
#include <cstdint>
#include <functional>
#include <algorithm>
#include <iostream>
template<typename Cont, typename F >
auto group_by (Cont c, F f) -> std::multimap< typename std::remove_reference<decltype(*std::begin(c))>::type, decltype(f(*std::begin(c)))> 
{
    std::multimap<typename std::remove_reference<decltype(*std::begin(c))>::type , decltype(f(*std::begin(c)))>  result;
    std::for_each(std::begin(c), std::end(c), 
        [&result,&f](typename Cont::value_type elem)
    {
        auto key = f(elem);
        result.insert(std::make_pair(key,elem));
    }
    );
    return result;
}
int main()
{
    std::deque<uint64_t> dq;
    std::deque<uint64_t>::value_type asghuitl;
    dq.push_back(1);
    dq.push_back(2);
    dq.push_back(11);
    dq.push_back(21);
    auto result = group_by(dq, [] (uint64_t x){return x%10;});

}
4

2 に答える 2

1

あなたが持っているコードは、ほとんど変更することなく配列に対して機能します。#include <iterator>まず、 、 for std::begin、およびが必要ですstd::end。第二に、あなたは通り過ぎるはずですconst&。最後に、いくつかtypedefの s を追加すると、関数の残りの部分がもう少し読みやすくなります。最終的には次のようになります。

template<typename Cont, typename F >
auto group_by (const Cont& c, F f) -> 
  std::multimap< typename std::remove_reference<decltype(*std::begin(c))>::type,    
                 decltype(f(*std::begin(c)))> 
{

    typedef typename std::remove_reference<decltype(*std::begin(c))>::type value_type;
    typedef decltype(f(*std::begin(c))) result_type;

    std::multimap<value_type, result_type>  result;
    std::for_each(std::begin(c), std::end(c), 
        [&result,&f](value_type elem)
    {
        auto key = f(elem);
        result.insert(std::make_pair(key,elem));
    }
    );
    return result;
}

これをもっと醜くすることはできますか?まあ、おそらくあまりないでしょう。特性を利用して、渡されたものの値の型を取得できます ( と同様iterator_traits):

template <typename T>
struct container_traits
{
    typedef typename T::value_type value_type;
};

template <typename T, std::size_t N>
struct container_traits<T[N]>
{
    typedef T value_type;
};

template <typename T>
struct container_traits<T*>
{
    typedef T value_type;
};

これとstd::result_of(必要type_traits)を利用する:

template<typename Cont, typename F>
auto group_by (const Cont& c, F f) -> 
    std::multimap<
      typename container_traits<Cont>::value_type, 
      typename std::result_of<F(typename container_traits<Cont>::value_type)>::type>
{
    typedef typename container_traits<Cont>::value_type value_type;
    typedef typename 
      std::result_of<F(typename container_traits<Cont>::value_type)>::type result_type;

    std::multimap<value_type, result_type>  result;
    std::for_each(std::begin(c), std::end(c), 
        [&result,&f](value_type elem)
    {
        auto key = f(elem);
        result.insert(std::make_pair(key,elem));
    }
    );
    return result;
}

ただし、これにはより多くのコードが必要です。ネーミングは正確に何が起こっているかについて少し明確かもしれませんが、decltype解決策はおそらく「よりクリーン」です。

于 2013-05-20T01:58:41.730 に答える