c++ - Decltype and templates - any way to make decltype machinery less complicated? -


i playing around implementing group_by method in generic way , have maybe implemented it(except doesnt work c arrays), still code looks ugly me...

is there easier way want(+ work containers , c arrays(i dont know how make work c arrays (t t) ) ?
if not obvious im talking types std::multimap... btw know c++14 remove need type 2 times( auto know type write after -> )

// group_by.cpp : defines entry point 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;});  } 

first step: make work c-style arrays.

second step: use range-based loop. less problems / effort.

third step: make bit nicer using template alias.

#include <iostream> #include <map> #include <deque> #include <cstdint> #include <functional> #include <algorithm> #include <iterator>  template < typename elem, typename res > using return_type = std::multimap < typename std::remove_reference<elem>::type,                                     res>;  template<typename cont, typename f > auto group_by (cont const& c, f const& f)     -> return_type < decltype(*std::begin(c)), decltype(f(*std::begin(c))) > {     return_type< decltype(*std::begin(c)),                  decltype(f(*std::begin(c))) >  result;      for(auto const& e : c)     {         auto const& key = f(e);         result.insert( std::make_pair(key,e) );         // alternatively, just:         // result.emplace( f(e), e );     }      return result; }  int main() {     char const foo[] = "hello world";     auto result = group_by(foo, [] (uint64_t x){return x%10;}); } 

visual-studio-supported version:

template < typename cont, typename f > auto group_by (cont const& c, f const& f)   -> std::multimap      <        typename std::remove_reference<decltype(*std::begin(c))>::type,        decltype(f(*std::begin(c)))      > {     using key_ref = decltype( *std::begin(c) );     using key_type = typename std::remove_reference < key_ref > :: type;     using value_type = decltype( f(*std::begin(c)) );      std::multimap < key_type, value_type > result;      for(auto const& e : c)     {         result.emplace( f(e), e );     }      return result; } 

fourth step: use iterators instead of passing container.

#include <iostream> #include <map> #include <deque> #include <cstdint> #include <functional> #include <algorithm> #include <iterator>  template < typename elem, typename res > using return_type = std::multimap< typename std::remove_reference<elem>::type,                                    res >;  template < typename fwdit, typename f > auto group_by (fwdit beg, fwdit end, f const& f)     -> return_type < decltype(*beg), decltype(f(*beg)) > {     return_type < decltype(*beg), decltype(f(*beg)) >  result;      for(fwdit = beg; != end; ++i)     {         result.emplace( f(*i), *i );     }      return result; }  int main() {     char const foo[] = "hello world";     auto result = group_by( std::begin(foo), std::end(foo),                             [] (uint64_t x){return x%10;}   ); } 

visual-studio-supported version:

template < typename fwdit, typename f > auto group_by (fwdit beg, fwdit end, f const& f)   -> std::multimap      <        typename std::remove_reference<decltype(*std::begin(c))>::type,        decltype(f(*std::begin(c)))      > {     using key_ref = decltype( *std::begin(c) );     using key_type = typename std::remove_reference < key_ref > :: type;     using value_type = decltype( f(*std::begin(c)) );      std::multimap < key_type, value_type > result;      for(fwdit = beg; != end; ++i)     {         result.emplace( f(*i), *i );     }      return result; } 

Comments

Popular posts from this blog

.htaccess - First slash is removed after domain when entering a webpage in the browser -

Automatically create pages in phpfox -

c# - Farseer ContactListener is not working -