Skip to content

Commit 13082d5

Browse files
paulpaul
authored andcommitted
Auto deduce return type for function objects
1 parent c1169e5 commit 13082d5

File tree

2 files changed

+57
-48
lines changed

2 files changed

+57
-48
lines changed

linq/extensions/detail/function_object.h

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define LINQ_GUARD_DETAIL_FUNCTION_OBJECT_H
1010

1111
#include <linq/utility.h>
12+
#include <linq/extensions/detail/result_of.h>
1213
#include <boost/optional.hpp>
1314
#include <utility>
1415

@@ -26,6 +27,12 @@ struct unwrap<std::reference_wrapper<T> >
2627
{
2728
typedef T& type;
2829
};
30+
template<class T>
31+
struct lazy_unwrap
32+
{
33+
typedef typename unwrap<typename T::type>::type type;
34+
};
35+
2936
}
3037

3138
// Lambdas aren't very nice, so we use this wrapper to make them play nicer. This
@@ -59,19 +66,20 @@ struct function_object
5966

6067
template<class F>
6168
struct result
69+
: detail::lazy_unwrap<linq::result_of<F> >
6270
{};
6371

64-
template<class F, class T>
65-
struct result<F(T)>
66-
{
67-
typedef typename detail::unwrap<decltype(linq::declval<F>()(linq::declval<T>()))>::type type;
68-
};
69-
70-
template<class F, class T, class U>
71-
struct result<F(T, U)>
72-
{
73-
typedef typename detail::unwrap<decltype(linq::declval<F>()(linq::declval<T>(), linq::declval<U>()))>::type type;
74-
};
72+
// template<class F, class T>
73+
// struct result<F(T)>
74+
// {
75+
// typedef typename detail::unwrap<decltype(linq::declval<F>()(linq::declval<T>()))>::type type;
76+
// };
77+
78+
// template<class F, class T, class U>
79+
// struct result<F(T, U)>
80+
// {
81+
// typedef typename detail::unwrap<decltype(linq::declval<F>()(linq::declval<T>(), linq::declval<U>()))>::type type;
82+
// };
7583

7684
template<class T>
7785
typename result<const Fun(T)>::type operator()(T && x) const

linq/extensions/group_by.h

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,54 +25,55 @@ namespace linq {
2525
// group_by
2626
//
2727
namespace detail {
28-
struct group_by_t
28+
29+
template<class KeySelector, class ElementSelector>
30+
struct group_by_map_selector
2931
{
30-
template<class KeySelector, class ElementSelector>
31-
struct map_selector
32+
KeySelector key_selector;
33+
ElementSelector element_selector;
34+
35+
group_by_map_selector(KeySelector key_selector, ElementSelector element_selector)
36+
: key_selector(key_selector), element_selector(element_selector)
37+
{}
38+
39+
template<class>
40+
struct result;
41+
42+
template<class F, class T>
43+
struct result<F(T)>
3244
{
33-
KeySelector key_selector;
34-
ElementSelector element_selector;
35-
36-
map_selector(KeySelector key_selector, ElementSelector element_selector)
37-
: key_selector(key_selector), element_selector(element_selector)
38-
{}
39-
40-
template<class>
41-
struct result;
42-
43-
template<class F, class T>
44-
struct result<F(T)>
45-
{
46-
typedef std::pair<typename linq::result_of<KeySelector(T)>::type, typename linq::result_of<ElementSelector(T)>::type > type;
47-
};
48-
49-
template<class F, class T>
50-
struct result<F(T&&)>
51-
: result<F(T)>
52-
{};
53-
54-
template<class T>
55-
typename result<map_selector(T&&)>::type operator()(T && x) const
56-
{
57-
return typename result_of<map_selector(T&&)>::type(key_selector(x), element_selector(x));
58-
}
45+
typedef std::pair<typename linq::result_of<KeySelector(T)>::type, typename linq::result_of<ElementSelector(T)>::type > type;
5946
};
6047

61-
template<class KeySelector, class ElementSelector>
62-
static map_selector < KeySelector, ElementSelector >
63-
make_map_selector (KeySelector && key_selector, ElementSelector && element_selector)
48+
template<class F, class T>
49+
struct result<F(T&&)>
50+
: result<F(T)>
51+
{};
52+
53+
template<class T>
54+
typename result<group_by_map_selector(T&&)>::type operator()(T && x) const
6455
{
65-
return map_selector < KeySelector, ElementSelector >
66-
(std::forward<KeySelector>(key_selector), std::forward<ElementSelector>(element_selector));
56+
return typename result<group_by_map_selector(T&&)>::type(key_selector(x), element_selector(x));
6757
}
58+
};
6859

60+
template<class KeySelector, class ElementSelector>
61+
group_by_map_selector < KeySelector, ElementSelector >
62+
make_group_by_map_selector (KeySelector && key_selector, ElementSelector && element_selector)
63+
{
64+
return group_by_map_selector < KeySelector, ElementSelector >
65+
(std::forward<KeySelector>(key_selector), std::forward<ElementSelector>(element_selector));
66+
}
67+
68+
struct group_by_t
69+
{
6970
template<class>
7071
struct result;
7172

7273
template<class F, class Range, class KeySelector, class ElementSelector>
7374
struct result<F(Range, KeySelector, ElementSelector)>
7475
{
75-
typedef typename as_unordered_map<typename result_of<detail::select_t(Range, map_selector<KeySelector, ElementSelector>)>::type >::type type;
76+
typedef typename as_unordered_map<typename result_of<detail::select_t(Range, group_by_map_selector<KeySelector, ElementSelector>)>::type >::type type;
7677
};
7778

7879
template<class F, class Range, class KeySelector, class ElementSelector>
@@ -88,7 +89,7 @@ struct group_by_t
8889
template<class Range, class KeySelector>
8990
auto operator()(Range && r, KeySelector ks) const LINQ_RETURNS
9091
(
91-
make_map( r | linq::select(make_map_selector(ks, identity_selector())) )
92+
make_map( r | linq::select(make_group_by_map_selector(ks, identity_selector())) )
9293
);
9394

9495
// TODO: Custom comparer overloads can't be supported right now,
@@ -98,7 +99,7 @@ struct group_by_t
9899
template<class Range, class KeySelector, class ElementSelector>
99100
auto operator()(Range && r, KeySelector ks, ElementSelector es) const LINQ_RETURNS
100101
(
101-
make_map( r | linq::select(make_map_selector(ks, es)) )
102+
make_map( r | linq::select(make_group_by_map_selector(ks, es)) )
102103
);
103104

104105
};

0 commit comments

Comments
 (0)