Get type from a templated range - c++

TL;DR
Given R as a template argument, for R being some_container<T> or T[], how to deduce T?
Possible implementation is std::iterator_traits<decltype(std::begin(r))>::value_type, looking for something less verbose.
Elaborated
I'm trying to implement a wrapper around std::accumulate algorithm, so that instead of typing this:
std::accumulate(v.begin(), v.end(), 0, [](int x, int y) { return x * y; });
user can simply write this:
my::accumulate(v, [](int x, int y) { return x * y; });
So basically, my::accumulate, given an entity and an operation, is intended to call std::accumulate with the following arguments:
std::begin() from the given entity
std::end() from the given entity
default-constructed value as a starting point
given operation
I use free begin and end functions to allow function work on built-in arrays. The passed entity is thus a range. Here is my implementation:
template<class R, typename F>
auto accumulate(const R& r, F&& f) ->
typename std::iterator_traits<decltype(std::begin(r))>::value_type
{
using T = std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}
It works fine. The only thing that bothers me is that ugly std::iterator_traits<decltype(std::begin(r))>::value_type construction. Is there a better way to get the type from the range? Note that R does not have to be a container, so I cannot use R::value_type.
Please note, that I'm using Visual Studio 2013, so I can use most of C++11 and some of C++14.
PS. Any other comments on the implementation? Are there any drawbacks or implications?

You could use typename std::remove_reference_t<decltype(*std::begin(r))> to save a few keystrokes, but it isn't much better.
I suppose you want to implement more algorithms than just accumulate, in which case you can create an alias for the element type:
template<typename T>
using value_type = typename std::iterator_traits<decltype(std::begin(T{}))>::value_type;
template<class R, typename F>
value_type<R> accumulate(const R& r, F&& f)
{
return std::accumulate(std::begin(r), std::end(r), value_type<R>{}, std::forward<F>(f));
}
Otherwise, you could use a placeholder return type to avoid the repetition:
template<class R, typename F>
auto accumulate(const R& r, F&& f)
{
using T = typename std::iterator_traits<decltype(std::begin(r))>::value_type;
return std::accumulate(std::begin(r), std::end(r), T{}, std::forward<F>(f));
}

Related

How does template function work with multiple typenames which may share an intersection?

I am new to C++ and currently trying to understand how template functions work. First I wanted to add two numerical values of the same type, which is quite easy to understand.
template <typename T>
T add(T a, T b){return a+b;}
int main(){
float a_f=2.5;float b_f=1.5;float c_f;
int a_i=2;int b_i=1;int c_i;
c_f = add(a_f, b_f);
c_i = add(a_i, b_i);
return 0;
}
Next I wanted to add two numerical numbers with different and equal types. My naive assumption was this:
template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}
int main(){
float a=3.2; int b=2;
auto result1 = add(a,b); // error: no matching function for call to ‘add(float&, int&)’
auto result2 = add(a,a); // error: no matching function for call to ‘add(float&, float&)’
auto result3 = add(b,b); // error: no matching function for call to ‘add(int&, int&)’
return 0;
}
I am aware that this approach is not correct, because the typename's share an intersection regarding data types and therefore the declaration itself cannot be correct.
How could a simple add() function be implemented that adds two numeric values together, regardless of type?
The problem is not with an intersection, but that it cant deduce R. In
template<typename R, typename S, typename T>
R add(S a, T b){return a+b;}
There is nothing telling the compiler what R should be. It's not deduced from the variable you are assigning the result to and you do not specify it, so there is no valid call that it can do. To fix this you can just get rid of R and use the auto return type to have it deduced for you like
template<typename S, typename T>
auto add(S a, T b){return a+b;}
How could a simple add() function be implemented that adds two numeric values together, regardless of type?
In C++14:
template<class T, class U>
auto add(T t, U u) {
return t + u;
}
In the above, the type of the return value is deduced from the type of expression t + u.
C++11 doesn't deduce return types but allows for trailing return type, so a C++11 version is:
template<class T, class U>
auto add(T t, U u) -> decltype(t + u) {
return t + u;
}
What you want is to deduce the return type. However, type deduction for type template parameter only apply for function parameter.
Even though typenames are not the right tool to do that, C++ offers other mean to deduce the type.
Use auto
You can simply put auto there and let the compiler deduce from the return type:
template<typename S, typename T>
auto add(S a, T b){ return a + b; }
Use trailing return types
You can also use the trailing return type if you want to be more explicit on the return type of the function:
template<typename S, typename T>
auto add(S a, T b) -> decltype(a + b) { return a + b; }

C++ can't derive template parameters for high-order functions

When I use have template function which accepts another function as a parameter, C++ can't derive template parameters. It's very annoying to specify them all the time. How can I define the following function such that I don't have to specify type parameters every time?
#include <functional>
template <typename S, typename T>
T apply(const S& source, const function<T (const S&)>& f) {
return f(source);
}
template <typename S, class Functor, typename T>
T applyFun(const S& source, const Functor& f) {
return f(source);
}
int main() {
// Can't derive T. Why?
apply(1, [](int x) { return x + 1; });
// Compiles
apply<int, int>(1, [](const int& x) { return x + 1; });
// Can't derive T. Kind of expected.
applyFun(1, [](int x) { return x + 1; });
}
It makes sense to me why it can't derive type parameter in the second function, but not in the first one (since x + 1 is int, so it should deduce that T = int).
A template parameter must appear in a function parameter type to be deductible. Moreover lambdas are not functions so, whatsoever the return type of a lambda cannot participate to template argument deduction.
But in this case, there is no need to specify the return type. Return type deduction can do the job:
template <typename S, class Functor>
auto applyFun(const S& source, const Functor& f) {
return f(source);
}
If you can use C++17, you can use the deduction guides for std::function as follows
template <typename S, typename F,
typename T = typename decltype( std::function{std::declval<F>()} )::result_type>
T applyFun (S const & source, F const & f)
{
return f(source);
}
but, as pointed by Oliv, for your example function there is non need of T because you can use auto (from C++14; auto ... -> decltype(f(source)) in C++11).
-- EDIT --
The OP say
The good thing about this solution is that I can use T inside the function (e.g. if I want to implement vector_map).
You can detect and use T, also inside the function, using a using
Something as
template <typename S, typename F>
auto applyFun (S const & source, F const & f)
{
using T = typename decltype( std::function{f} )::result_type;
return f(source);
}
or simpler: using T = decltype( f(source) );.
The OP also observe that
The downside is that for some reason now I can't write [] (const auto& x) { ... } in function call.
Correct.
Because std::function template types can't be deduced from a generic-lambda.
But using the fact that you know the type of the argument, you can use decltype() again
template <typename S, typename F,
typename T = decltype(std::declval<F const>()(std::declval<S const>()))>
T applyFun (S const & source, F const & f)
{ return f(source); }
This solution should works also for C++14 and C++11.

How to iterate over a std::tuple in C++ 11 [duplicate]

This question already has answers here:
How can you iterate over the elements of an std::tuple?
(23 answers)
Closed 8 years ago.
I have made the following tuple:
I want to know how should I iterate over it? There is tupl_size(), but reading the documentation, I didn't get how to utilize it. Also I have search SO, but questions seem to be around Boost::tuple .
auto some = make_tuple("I am good", 255, 2.1);
template<class F, class...Ts, std::size_t...Is>
void for_each_in_tuple(const std::tuple<Ts...> & tuple, F func, std::index_sequence<Is...>){
using expander = int[];
(void)expander { 0, ((void)func(std::get<Is>(tuple)), 0)... };
}
template<class F, class...Ts>
void for_each_in_tuple(const std::tuple<Ts...> & tuple, F func){
for_each_in_tuple(tuple, func, std::make_index_sequence<sizeof...(Ts)>());
}
Usage:
auto some = std::make_tuple("I am good", 255, 2.1);
for_each_in_tuple(some, [](const auto &x) { std::cout << x << std::endl; });
Demo.
std::index_sequence and family are C++14 features, but they can be easily implemented in C++11 (there are many available on SO). Polymorphic lambdas are also C++14, but can be replaced with a custom-written functor.
Here is an attempt to break down iterating over a tuple into component parts.
First, a function that represents doing a sequence of operations in order. Note that many compilers find this hard to understand, despite it being legal C++11 as far as I can tell:
template<class... Fs>
void do_in_order( Fs&&... fs ) {
int unused[] = { 0, ( (void)std::forward<Fs>(fs)(), 0 )... }
(void)unused; // blocks warnings
}
Next, a function that takes a std::tuple, and extracts the indexes required to access each element. By doing so, we can perfect forward later on.
As a side benefit, my code supports std::pair and std::array iteration:
template<class T>
constexpr std::make_index_sequence<std::tuple_size<T>::value>
get_indexes( T const& )
{ return {}; }
The meat and potatoes:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
do_in_order( [&]{ f( get<Is>(std::forward<Tuple>(tup)) ); }... );
}
and the public-facing interface:
template<class Tuple, class F>
void for_each( Tuple&& tup, F&& f ) {
auto indexes = get_indexes(tup);
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f) );
}
while it states Tuple it works on std::arrays and std::pairs. It also forward the r/l value category of said object down to the function object it invokes. Also note that if you have a free function get<N> on your custom type, and you override get_indexes, the above for_each will work on your custom type.
As noted, do_in_order while neat isn't supported by many compilers, as they don't like the lambda with unexpanded parameter packs being expanded into parameter packs.
We can inline do_in_order in that case
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
int unused[] = { 0, ( (void)f(get<Is>(std::forward<Tuple>(tup)), 0 )... }
(void)unused; // blocks warnings
}
this doesn't cost much verbosity, but I personally find it less clear. The shadow magic of how do_in_order works is obscured by doing it inline in my opinion.
index_sequence (and supporting templates) is a C++14 feature that can be written in C++11. Finding such an implementation on stack overflow is easy. A current top google hit is a decent O(lg(n)) depth implementation, which if I read the comments correctly may be the basis for at least one iteration of the actual gcc make_integer_sequence (the comments also point out some further compile-time improvements surrounding eliminating sizeof... calls).
Alternatively we can write:
template<class F, class...Args>
void for_each_arg(F&&f,Args&&...args){
using discard=int[];
(void)discard{0,((void)(
f(std::forward<Args>(args))
),0)...};
}
And then:
template<size_t... Is, class Tuple, class F>
void for_each( std::index_sequence<Is...>, Tuple&& tup, F&& f ) {
using std::get;
for_each_arg(
std::forward<F>(f),
get<Is>(std::forward<Tuple>(tup))...
);
}
Which avoids the manual expand yet compiles on more compilers. We pass the Is via the auto&&i parameter.
In C++1z we can also use std::apply with a for_each_arg function object to do away with the index fiddling.
Here is a similar and more verbose solution than the formerly accepted one given by T.C., which is maybe a little bit easier to understand (-- it's probably the same as thousand others out there in the net):
template<typename TupleType, typename FunctionType>
void for_each(TupleType&&, FunctionType
, std::integral_constant<size_t, std::tuple_size<typename std::remove_reference<TupleType>::type >::value>) {}
template<std::size_t I, typename TupleType, typename FunctionType
, typename = typename std::enable_if<I!=std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type >
void for_each(TupleType&& t, FunctionType f, std::integral_constant<size_t, I>)
{
f(std::get<I>(std::forward<TupleType>(t)));
for_each(std::forward<TupleType>(t), f, std::integral_constant<size_t, I + 1>());
}
template<typename TupleType, typename FunctionType>
void for_each(TupleType&& t, FunctionType f)
{
for_each(std::forward<TupleType>(t), f, std::integral_constant<size_t, 0>());
}
Usage (with std::tuple):
auto some = std::make_tuple("I am good", 255, 2.1);
for_each(some, [](const auto &x) { std::cout << x << std::endl; });
Usage (with std::array):
std::array<std::string,2> some2 = {"Also good", "Hello world"};
for_each(some2, [](const auto &x) { std::cout << x << std::endl; });
DEMO
General idea: as in the solution of T.C., start with an index I=0 and go up to the size of the tuple. However, here it is done not per variadic expansion but one-at-a-time.
Explanation:
The first overload of for_each is called if I is equal to the size of the tuple. The function then simply does nothing and such end the recursion.
The second overload calls the function with the argument std::get<I>(t) and increases the index by one. The class std::integral_constant is needed in order to resolve the value of I at compile time. The std::enable_if SFINAE stuff is used to help the compiler separate this overload from the previous one, and call this overload only if the I is smaller than the tuple size (on Coliru this is needed, whereas in Visual Studio it works without).
The third starts the recursion with I=0. It is the overload which is usually called from outside.
EDIT: I've also included the idea mentioned by Yakk to additionally support std::array and std::pair by using a general template parameter TupleType instead of one that is specialized for std::tuple<Ts ...>.
As TupleType type needs to be deduced and is such a "universal reference", this further has the advantage that one gets perfect forwarding for free. The downside is that one has to use another indirection via typename std::remove_reference<TupleType>::type, as TupleType might also be a deduced as a reference type.

std algorithms with pointer to member as comparator/"key"

I often find myself using std::sort, std::max_element, and the like with a lambda that simply invokes a member function
std::vector<MyType> vec;
// populate...
auto m = std::max_element(std::begin(vec), std::end(vec),
[](const MyType& a, const MyType& b) { return a.val() < b.val()})
this feels like a waste of characters and a loss of clarity. I'm aware that I could write another function/callable and pass a function pointer/callable object to these algorithm functions, but I often need to do this sort-by just once in a program and it doesn't strike me as a good way of addressing the problem. What I want to do, ideally is say:
auto m = std::max_element(std::begin(vec), std::end(vec), &MyType::val);
and have the objects be sorted by their val()s. Is there some part of the stdlib I'm overlooking that could assist me with this? or another simple way of doing it? I'd like to make what this is sorting or searching by as obvious as possible.
I'm aware that just &MyType::val isn't enough, I am looking for something that could perhaps wrap it, or provide a similar functionality without obscurring the meaning.
You can use std::mem_fn (or std::tr1::mem_fn)
int main()
{
std::vector<MyType> vec;
auto m = std::max_element(std::begin(vec), std::end(vec), compare_by(std::mem_fn(&MyType::field)));
}
Of course, this assumes that you have a utility like compare_by in your toolbox (as you should :)):
template <typename F>
struct CompareBy {
explicit CompareBy(F&& f) : f(std::forward<F>(f)) {}
template <typename U, typename V>
bool operator()(U const& u, V const& v) const {
return f(u) < f(v);
}
private:
F f;
};
template <typename F>
CompareBy<F> compare_by(F&& f) { return CompareBy<F>(std::forward<F>(f)); }
See it Live On Coliru
You can do it without introducing any new functions (templated or not).
Just use bind and std::less
auto m = std::max_element(vec.begin(), vec.end(),
bind(less<>(), bind(&MyType::val, _1), bind(&MyType::val, _2)));
A templated comparator could help you:
template <typename StructureType,
typename MemberType,
MemberType StructureType::*member>
bool comparator(const StructureType& the_first, const StructureType& the_second)
{
return the_first.*member < the_second.*member;
}
http://ideone.com/K8ytav
A bit of type traits magic could certainly allows you to avoid writing the type.
How about once overloading operator< for your custom type? This can be naturally done inside the class (or directly next to it), and then no further argument is required beside the iterators.
Passing your val() function isn't possible, as you must pass a binary operator.
EDIT: Having read the other valuable alternatives (also sehe's nice response), I want to confirm what I already mentioned in the comment below: In my opinion, nothing beats the readibility, locality and also flexibility of a lambda expression (--on the risk of writing some passages twice).
#Ryan Haining: I suggest you to keep it as in your original post.
An improvement on sehes answer, so as to avoid needing to use std::mem_fn would be provide a pointer to member overload for the compare_by function.
example usage
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field));
std::sort(std::begin(vec), std::end(vec), compare_by(&MyType::field, std::greater<>{}));
the code to implement
#include <functional> // std::less
#include <utility> // std::move
#include <type_traits> // std::is_invocable_r
// Forward declaration
template<typename R, typename T, typename F = std::less<R>>
auto compare_by(R T::*, F = F{});
// Implementation
namespace detail {
template<typename T, typename F>
struct compare_by_t;
template<typename R, typename T, typename F>
struct compare_by_t<R T::*, F> : private F
{
compare_by_t(F&& f, R T::*m): F{std::move(f)}, _member{m} {}
R T::* _member;
bool operator()(T const& x, T const& y) const
{
return F::operator()(x .* _member, y .* _member);
}
};
} // detail
template<typename R, typename T, typename F>
auto compare_by(R T::* member, F f)
{
static_assert(std::is_invocable_r<bool, F, R, R>::value);
return detail::compare_by_t<R T::*, F>{ std::move(f), member };
}

C++ overloading by functor param count type

I am working on "LINQ to Objects" library for C++11.
I would like to do smth like this:
// filtering elements by their value
arr.where( [](double d){ return d < 0; } )
// filtering elements by their value and position
arr.where( [](double d, int i){ return i%2==0; } )
I down want to write arr.where_i( ... ) - it's ugly.
So i need function/method overloading by lambda-type...
This is my solution:
template<typename F>
auto my_magic_func(F f) -> decltype(f(1))
{
return f(1);
}
template<typename F>
auto my_magic_func(F f, void * fake = NULL) -> decltype(f(2,3))
{
return f(2,3);
}
int main()
{
auto x1 = my_magic_func([](int a){ return a+100; });
auto x2 = my_magic_func([](int a, int b){ return a*b; });
// x1 == 1+100
// x2 == 2*3
}
Is it SFINAE solution?
What can you suggest me?
Maybe something variadic:
#include <utility>
template <typename F, typename ...Args>
decltype(f(std::declval<Args>()...) my_magic_func(F f, Args &&... args)
{
return f(std::forward<Args>(args)...);
}
Edit: You can also use typename std::result_of<F(Args...)>::type for the return type, which does the same thing.
You certainly want SFINAE in your solution. Generally speaking, the result would look something like:
template<
typename Functor
, typename std::enable_if<
special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
template<
typename Functor
, typename std::enable_if<
!special_test<Functor>::value
, int
>::type = 0
>
return_type
my_magic_func(Functor f);
such that only one overload would be active at any one time -- all that remains now is carefully crafting that special_test to have the behaviour we want. This is a careful balancing act as you don't want the test to be too specific; otherwise we lose generality. Quite a shame when writing generic code. You haven't given too much information (e.g. are you strictly interested in support for lambdas? monomorphic functors? polymorphic functors?), but I will assume for now that we have access to a value_type alias which would correspond to double in your example.
As such, here's an example condition that will check that a given type is Callable (that's a Standard concept) with signature bool(value_type); i.e. that it's a predicate of sorts:
template<typename Functor, typename ValueType>
struct is_unary_predicate {
typedef char (&accepted)[1];
typedef char (&refused)[2];
void consume(bool);
template<
typename X
, typename Y
, typename = decltype( consume(std::declval<X>()(std::declval<Y>())) )
>
accepted
test(X&&, Y&&);
refused test(...);
static constexpr bool value =
sizeof test(std::declval<Functor>(), std::declval<ValueType>())
== sizeof(accepted);
};
Personally I have an is_callable<F, Signature> trait so that I would only need to write something like template<typename Functor, typename ValueType> using is_unary_predicate = is_callable<Functor, bool(ValueType)>; (and similarly I could have an is_binary_predicate alias instead of letting the second overload of my_magic_func be a catch-all). Perhaps you'd want to use a similar trait for future uses of SFINAE (although it may be somewhat painful to write without variadic templates).