Consider the following (https://godbolt.org/z/sfT3aesvK):
#include <utility>
#include <vector>
struct A { constexpr static int type = 0; };
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A>(std::forward<Args>(args)...);
};
std::vector<int(*)(Args&&...) /* what goes here? */> vec{{call_with_A}};
int acc = 0;
for (auto fn : vec) {
acc += fn(std::forward<Args>(args)...);
}
return acc;
}
int bar() {
return 1 + foo([]<typename T>(int a, int b) {
return T::type + a + b;
}, 2, 3);
}
The above does not compile, because
no known conversion from '(lambda at <source>:8:24)' to 'int (*)(int &&, int &&)' for 1st argument
My question is what the template type T so that std::vector<T> will accept call_with_A as an element?
I tried to print what decltype(call_with_A) is, but this seems to just be a (lambda at [...]) expression for the compiler.
The type of a lambda expression is "unutterable". It cannot be written down directly. However, you can declare a typedef alias for the type:
auto call_with_A = /* lambda */;
using LambdaType = decltype(call_with_A);
std::vector<LambdaType> vec = {call_with_A};
You can also use class template argument deduction if you don't need to mention the type anyway:
auto call_with_A = /* lambda */;
std::vector vec = {call_with_A};
// the type of `vec` is `std::vector<decltype(call_with_A)>`
Every lambda has a different type - even they have the same signature. Lambda functions that have identical body also have different type.
You can declare a vector of type using decltype. However, it is not useful. For example.
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
std::vector<decltype(call_with_A)> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1); // Not OK
vec.push_back(call_with_A2); // Not OK
return 0;
}
Your best option is to use std::vector of std::function. For example.
template <typename Func, typename... Args>
int foo(Func func, Args&& ... args) {
auto call_with_A = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A1 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
auto call_with_A2 = [func](Args&& ... args) {
return func.template operator()<A1>(std::forward<Args>(args)...);
};
std::vector<std::function<int(Args...)>> vec;
vec.push_back(call_with_A);
vec.push_back(call_with_A1);
vec.push_back(call_with_A2);
return 0;
}
Related
related post: How to combine std::bind(), variadic templates, and perfect forwarding?
Is there a way to bind a function with variadic tuples ? Here incorrect code indicating the intent:
// t is an instance of T
auto f = std::bind(&T::iterate,t,???);
// args is an instance of std::tuple<Args...> args;
std::apply(f,args);
(note: I am unsure "variadic tuple" to be the right terminology. Looking forward editing the post with your correction)
Since C++20 you can use std::bind_front:
template<class T>
void print (T val) {
std::cout << val << std::endl;
}
struct T {
template<class ... Args>
void iterate(Args... args) {
int temp[] = { (print(args),0)... };
}
};
// all happens here
template<class ... Args>
void foo(const tuple<Args...>& args) {
T t;
auto f = std::bind_front(&T::iterate<Args...>,&t);
std::apply(f,args);
}
// the call
int i = 1;
foo(std::make_tuple(i,i+1,"bind is cool"));
If you want to use old std::bind, you can provide your own placeholders to be generated from pack:
template<int N>
struct MyPlaceholder {};
namespace std {
template<int N>
struct is_placeholder<MyPlaceholder<N>> : public integral_constant<int, N> {};
}
template<class ... Args, size_t ... Indices>
void foo2helper(const tuple<Args...>& args, std::index_sequence<Indices...>) {
T t;
auto f = std::bind(&T::iterate<Args...>,&t, (MyPlaceholder<Indices+1>{})...);
std::apply(f,args);
}
template<class ... Args>
void foo2(const tuple<Args...>& args) {
foo2helper(args, std::make_index_sequence<sizeof...(Args)>{});
}
// the call
foo2(std::make_tuple(2.34,"only bind"));
Live demo
Don't use bind, use a lambda instead:
auto f = [&t](auto... args){ t.iterate(args...); };
std::apply(f, args);
If you want perfect forwarding, that would look like:
auto f = [&t](auto&&... args){ t.iterate(std::forward<decltype(args)>(args)...); };
std::apply(f, args);
For a set of N functions fs... each taking only a single argument, I would like to create an object which has a call operator taking N arguments args..., calls all functions fs(args)... and returns outputs as a tuple.
The basic class would look something like this. I have marked the places I do not know how to implement with ???.
template <class... Fs>
struct merge_call_object {
merge_call_object(Fs... _fs)
: fs(std::move(_fs)...) {}
template <class... Args>
auto operator()(Args &&... args) -> decltype(???){
???
}
std::tuple<Fs...> fs;
};
The expected usage of this object would be:
auto f1 = [](double x){ return 2*s; };
auto f2 = [](std::string const& s){ return s+" World!"; };
auto mco = merge_call_object{f1,f2};
// The following should yield std::tuple{42, "Hello World!"}
auto out = mco(21, "Hello ");
So far so good, doing the above is "easy" but I want that overloading for mco works as expected i.e. the following should compile and pass
static_assert(std::is_invocable_v<decltype(mco), double, std::string> == true);
static_assert(std::is_invocable_v<decltype(mco), double, double> == false);
The biggest challenge I see is how implement correctly the SFINAE -> decltype(???).
This question is inspired by the recent talk from CppCon Overloading: The Bane of All Higher-Order Functions, around 6:40 he talks about how to wrap a function into a lambda.
My implementation without the correct overload set, plus a small test on perfect forwarding.
#include <iostream>
#include <tuple>
#include <utility>
namespace detail {
template <std::size_t... I>
constexpr auto integral_sequence_impl(std::index_sequence<I...>) {
return std::make_tuple((std::integral_constant<std::size_t, I>{})...);
}
template <std::size_t N, typename Indices = std::make_index_sequence<N>>
constexpr auto integral_sequence = integral_sequence_impl(Indices{});
template <std::size_t N, typename Fun>
constexpr decltype(auto) apply_sequence(Fun &&fun) {
return std::apply(std::forward<Fun>(fun), detail::integral_sequence<N>);
}
} // namespace detail
template <class... Fs>
struct merge_call_object {
merge_call_object(Fs... _fs)
: fs(std::move(_fs)...) {}
template <class... Args>
auto operator()(Args &&... args) {
constexpr int N = sizeof...(Fs);
auto f = [&](auto I) { return std::get<I>(fs); };
auto arg = [&](auto I) -> decltype(auto) {
return std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...));
};
return detail::apply_sequence<N>(
[&](auto... Is) { return std::forward_as_tuple(f(Is)(arg(Is))...); });
}
std::tuple<Fs...> fs;
};
struct Screamer {
Screamer() { std::cout << "Constructor!" << std::endl; }
Screamer(Screamer &&s) { std::cout << "Move constructor!" << std::endl; }
Screamer(Screamer const &s) { std::cout << "Copy constructor!" << std::endl; }
};
int main() {
auto f1 = [](auto &&x) -> decltype(auto) {
std::cout << "Calling f1" << std::endl;
return std::forward<decltype(x)>(x);
};
auto f2 = [](auto &&x) -> decltype(auto) {
std::cout << "Calling f2" << std::endl;
return std::forward<decltype(x)>(x);
};
auto mco = merge_call_object{f1, f2};
auto [s1, s2] = mco(Screamer{}, Screamer{});
return 0;
}
Since you have a direct one argument, one function mapping, all you really need is std::apply:
template <class... Args>
auto operator()(Args&&... args) {
return std::apply([&](Fs&... fs){
return std::tuple(fs(std::forward<Args>(args))...);
}, fs);
}
This will decay all of the types (that is, if some function/argument pair actually returns an int&, this will give you an int in that spot instead). This also isn't SFINAE-friendly.
A solution that is both SFINAE-friendly and maintains references just needs an extra dash of fold-expression:
template <class... Args,
std::enable_if_t<(std::is_invocable_v<Fs&, Args> && ...), int> = 0>
auto operator()(Args&&... args) {
return std::apply([&](Fs&... fs){
return std::tuple<std::invoke_result_t<Fs&, Args>...>(
fs(std::forward<Args>(args))...);
}, fs);
}
You have to use auto f() -> decltype(RET) { return RET; } way (Macro can be used to avoid the boiler plate :-/ and we can also handle noexcept).
Something like:
template <class... Fs>
struct merge_call_object {
private:
std::tuple<Fs...> fs;
private:
template <std::size_t... Is, typename Tuple>
auto call(std::index_sequence<Is...>, Tuple&& tuple)
-> decltype(std::make_tuple(std::get<Is>(fs)(std::get<Is>(std::forward<Tuple>(tuple)))...))
{
return std::make_tuple(std::get<Is>(fs)(std::get<Is>(std::forward<Tuple>(tuple)))...);
}
public:
merge_call_object(Fs... _fs)
: fs(std::move(_fs)...) {}
template <class... Args>
auto operator()(Args &&... args)
-> decltype(call(std::index_sequence_for<Fs...>(), std::forward_as_tuple(std::forward<Args>(args)...)))
{
return call(std::index_sequence_for<Fs...>(), std::forward_as_tuple(std::forward<Args>(args)...));
}
};
Demo
Given two or more example functions, is it possible to write templated code which would be able to deduce the arguments of a function provided as a template parameter?
This is the motivating example:
void do_something(int value, double amount) {
std::cout << (value * amount) << std::endl;
}
void do_something_else(std::string const& first, double & second, int third) {
for(char c : first)
if(third / c == 0)
second += 13.7;
}
template<void(*Func)(/*???*/)>
struct wrapper {
using Args = /*???*/;
void operator()(Args&& ... args) const {
Func(std::forward<Args>(args)...);
}
};
int main() {
wrapper<do_something> obj; //Should be able to deduce Args to be [int, double]
obj(5, 17.4); //Would call do_something(5, 17.4);
wrapper<do_something_else> obj2; //Should be able to deduce Args to be [std::string const&, double&, int]
double value = 5;
obj2("Hello there!", value, 70); //Would call do_something_else("Hello there!", value, 70);
}
In both uses of /*???*/, I am trying to work out what I could put there that would enable this kind of code.
The following doesn't appear to work, due to Args not being defined before its first use (along with what I have to assume are numerous syntax errors besides), and even if it did, I'm still looking for a version that doesn't require explicit writing of the types themselves:
template<void(*Func)(Args ...), typename ... Args)
struct wrapper {
void operator()(Args ...args) const {
Func(std::forward<Args>(args)...);
}
};
wrapper<do_something, int, double> obj;
With C++17 we can have auto template non-type parameters which make possible the Wrapper<do_something> w{} syntax 1).
As for deducing Args... you can do that with a specialization.
template <auto* F>
struct Wrapper {};
template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<F>
{
auto operator()(Args... args) const
{
return F(args...);
}
};
Wrapper<do_something> w{};
w(10, 11.11);
1) Without C++17 it's impossible to have the Wrapper<do_something> w{} nice syntax.
The best you can do is:
template <class F, F* func>
struct Wrapper {};
template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<Ret (Args...), F>
{
auto operator()(Args... args) const
{
return F(args...);
}
};
Wrapper<declype(do_something), do_something> w{};
With C++17, you can do this:
template <auto FUNC, typename = decltype(FUNC)>
struct wrapper;
template <auto FUNC, typename RETURN, typename ...ARGS>
struct wrapper<FUNC, RETURN (*)(ARGS...)> {
RETURN operator()(ARGS ...args) {
return FUNC(args...);
}
};
I've learned this technique from W.F.'s answer
Further improvement of C++17 version: less template parameters and proper noexcept annotation:
template<auto VFnPtr> struct
wrapper;
template<typename TResult, typename... TArgs, TResult ( * VFnPtr)(TArgs...)> struct
wrapper<VFnPtr>
{
TResult
operator ()(TArgs... args) const noexcept(noexcept((*VFnPtr)(::std::forward<TArgs>(args)...)))
{
return (*VFnPtr)(::std::forward<TArgs>(args)...);
}
};
With C++11 you can consider a templated make_wrapper helper function. However, with this approach the function pointer is not a template parameter. Instead, the function pointer is "carried" by the non-static data member called f_ in the following example:
#include <iostream>
void do_something(int value, double amount) {
std::cout << (value * amount) << std::endl;
}
void do_something_else(std::string const& first, double & second, int third) {
for(char c : first)
if(third / c == 0)
second += 13.7;
}
template<class Ret, class... Args>
using function_pointer = Ret(*)(Args...);
template<class Ret, class... Args>
struct wrapper {
using F = function_pointer<Ret, Args...>;
F f_;
explicit constexpr wrapper(F f) noexcept : f_{f} {}
template<class... PreciseArgs>// not sure if this is required
Ret operator()(PreciseArgs&&... precise_args) const {
return f_(std::forward<PreciseArgs>(precise_args)...);
}
};
template<class Ret, class... Args>
constexpr auto make_wrapper(
function_pointer<Ret, Args...> f
) -> wrapper<Ret, Args...> {
return wrapper<Ret, Args...>(f);
}
int main() {
constexpr auto obj = make_wrapper(do_something);
obj(5, 17.4);
constexpr auto obj2 = make_wrapper(do_something_else);
double value = 5;
obj2("Hello there!", value, 70);
return 0;
}
I am trying to write code to do something similar (code written for demonstration purposes) to this:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo([func](Args... args) -> std::result_of<F>::type
{
// Do something before calling func
func(args...);
// Do something after call func
});
}
So basically I am trying to write a function that returns an object that takes lambda that matches the templated function type. Obviously this code won't work because I do not have Args... defined. How would I solve this in C++11?
template<class F_before, class F, class F_after>
struct decorate_func_t {
F_before f0;
F f1;
F_after f2;
template<class...Args>
typename std::result_of<F(Args...)>::type operator()(Args&&...args)const{
f0();
auto r = f1(std::forward<Args>(args)...);
f2();
return r;
}
};
template<class F_before, class F, class F_after>
decorate_func_t<F_before, F, F_after>
decorate_func( F_before before, F f, F_after after ){
return {std::move(before), std::move(f), std::move(after)};
}
Then:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo(decorate_func(
[]{/* Do something before calling func */},
func,
[]{/* Do something after call func */ }
};
}
the lack of auto parameters in C++11 lambdas makes this about the best you can do.
In C++14 this is trivial:
template <class F>
auto runFunc(F func)
{
return foo(
[func](auto&&... args) // ->decltype(auto) maybe
{
// Do something before calling func
auto r = func(decltype(args)(args)...);
// Do something after call func
return r;
}
);
}
note that many nominally C++11 compilers actually support auto parameters on lambdas.
You can use a support structure as in the following example:
#include<type_traits>
#include<cassert>
struct foo {
template<typename F>
foo(F f) { assert(42 == f(42)); }
};
template<typename>
struct S;
template<typename R, typename... Args>
struct S<R(*)(Args...)> {
template <typename F>
static auto runFunc(F func) -> foo
{
return foo{[func](Args... args) -> R
{
// Do something before calling func
auto r = func(args...);
// Do something after call func
return r;
}};
}
};
template<typename F>
inline auto runFunc(F func) -> foo
{
return S<F>::runFunc(func);
}
int f(int i) { return i; }
int main() {
runFunc(f);
}
For it's not clear to me what's the context of the problem, I'm not sure I got exactly what you were asking for.
I hope the code above can help you.
Still being unsure it this is what you're searching for, I risk posting:
#include <iostream>
struct foo
{
template<typename T>
foo(T lambda)
{
lambda(1, 2);
}
};
template <typename F, typename... Args>
inline typename std::result_of<F>::type runFunc(F func)
{
return foo(
[func](Args... args)
{
std::cout << "Before";
func(args...);
std::cout << "After";
}
);
}
struct print
{
void operator()(int i) const
{
std::cout << i << std::endl;
}
void operator()(int i, int j) const
{
std::cout << i << " " << j << std::endl;
}
};
int main()
{
runFunc<print, int, int>(print());
}
I have the following piece of code (c++11):
template <typename F,
typename FirstT,
typename... FIn>
auto min_on(F f, FirstT first, FIn... v) -> typename std::common_type<FirstT, FIn...>::type
{
using rettype = typename std::common_type<FirstT, FIn...>::type;
using f_rettype = decltype(f(first));
rettype result = first;
f_rettype result_trans = f(first);
f_rettype v_trans;
(void)std::initializer_list<int>{
((v_trans = f(v), v_trans < result_trans)
? (result = static_cast<rettype>(v), result_trans = v_trans, 0)
: 0)...};
return result;
}
Which basically returns the argument result that produced the minimum value for expression f(result). This can be called like this:
auto mod7 = [](int x)
{
return x % 7;
};
auto minimum = min_on(mod7, 2, 8, 17, 5);
assert( minimum == 8); // since 8%7 = 1 -> minimum value for all arguments passed
Now I would like to use this in a 'curried' way so that I can get a variadic lambda from min_on and then call it with arguments (that I might receive later), like so:
auto mod7 = [](int x)
{
return x % 7;
};
auto f_min = min_on(mod7);
auto minimum = f_min(2, 8, 17, 5);
// or
auto minimum = min_on(mod7)(2, 8, 17, 5);
Is this even possible?
In C++11, the following works if you’re willing to manually create the function object:
template <typename F>
struct min_on_t {
min_on_t(F f) : f(f) {}
template <typename T, typename... Ts>
auto operator ()(T x, Ts... xs) -> typename std::common_type<T, Ts...>::type
{
// Magic happens here.
return f(x);
}
private: F f;
};
template <typename F>
auto min_on(F f) -> min_on_t<F>
{
return min_on_t<F>{f};
}
And then call it:
auto minimum = min_on(mod7)(2, 8, 17, 5);
To use lambdas in C++14, you need to omit the trailing return type because you cannot specify the type of the lambda without assigning it to a variable first, because a lambda expression cannot occur in an unevaluated context.
template <typename F>
auto min_on(F f)
{
return [f](auto x, auto... xs) {
using rettype = std::common_type_t<decltype(x), decltype(xs)...>;
using f_rettype = decltype(f(x));
rettype result = x;
f_rettype result_trans = f(x);
(void)std::initializer_list<int>{
(f(xs) < result_trans
? (result = static_cast<rettype>(xs), result_trans = f(xs), 0)
: 0)...};
return result;
};
}
Not sure on C++11, but in C++14, you could create a lambda to wrap your function in:
auto min_on_t = [](auto f) {
return [=](auto ... params) {
return min_on(f, params...);
};
};
auto min_t = min_on_t(mod7);
auto minimum = min_t(2, 8, 17, 5);
Live on Coliru
In C++14 this is easy.
template<class F>
auto min_on( F&& f ) {
return [f=std::forward<F>(f)](auto&& arg0, auto&&...args) {
// call your function here, using decltype(args)(args) to perfect forward
};
}
Many compilers got auto return type deduction and arguments in lambdas working prior to full C++14 support. So a nominal C++11 compiler might be able to compile this:
auto min_on = [](auto&& f) {
return [f=decltype(f)(f)](auto&& arg0, auto&&...args) {
// call your function here, using decltype(args)(args) to perfect forward
};
}
in C++11:
struct min_on_helper {
template<class...Args>
auto operator()(Args&&...args)
-> decltype( min_on_impl(std::declval<Args>()...) )
{
return min_on_impl(std::forward<Args>(args)...);
}
};
is boilerplate. This lets us pass the entire overload set of min_on_impl around as one object.
template<class F, class T>
struct bind_1st_t {
F f;
T t;
template<class...Args>
typename std::result_of<F&(T&, Args...)>::type operator()(Args&&...args)&{
return f( t, std::forward<Args>(args)... );
}
template<class...Args>
typename std::result_of<F const&(T const&, Args...)>::type operator()(Args&&...args)const&{
return f( t, std::forward<Args>(args)... );
}
template<class...Args>
typename std::result_of<F(T, Args...)>::type operator()(Args&&...args)&&{
return std::move(f)( std::move(t), std::forward<Args>(args)... );
}
};
template<class F, class T>
bind_1st_t< typename std::decay<F>::type, typename std::decay<T>::type >
bind_1st( F&& f, T&& t ) {
return {std::forward<F>(f), std::forward<T>(t)};
}
gives us bind_1st.
template<class T>
auto min_on( T&& t )
-> decltype( bind_1st( min_on_helper{}, std::declval<T>() ) )
{
return bind_1st(min_on_helper{}, std::forward<T>(t));
}
is modular and solves your problem: both min_on_helper and bind_1st can be tested independently.
You can also replace bind_1st with a call to std::bind, but in my experience the quirks of std::bind make me extremely cautious about recommending that to anyone.