C++ std::async() terminate on exception before calling future.get() - c++

I am trying to create a wrapper that calls std::terminate() when it catch an exception.
I would like this wrapper to take the same arguments as std::async() (it could be a call to a function as well as a call to a method).
Someone know how to make this code to compile ?
Thank you
http://ideone.com/tL7mTv
#include <iostream>
#include <functional>
#include <future>
template<class Fn, class... Args>
inline auto runTerminateOnException(Fn&& fn, Args&&... args) {
try {
return std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)();
} catch (...) {
std::terminate();
}
}
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
return std::async(std::launch::async, runTerminateOnException<Fn, Args&&...>, std::forward<Fn>(fn), std::forward<Args>(args)...);
}
struct Foo {
void print() {
printf("Foo::print()\n");
}
};
int main() {
Foo foo;
std::future<void> future = runAsyncTerminateOnException(&Foo::print, &foo);
// your code goes here
return 0;
}

I personally think you over complicated it a bit. You can just bind the call and use a simple lambda to do the wrapping.
#include <iostream>
#include <future>
#include <functional>
#include <type_traits>
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
auto make_call = std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...);
return std::async(std::launch::async, [=]() -> decltype(make_call()) {
try {
return make_call();
} catch (...) {
std::cout << "Terminate Called!" << std::endl;
std::terminate();
}
});
}
struct Foo {
void print() {
printf("Foo::print()\n");
}
void print2() {
printf("Foo::print2()\n");
throw 1;
}
};
int main() {
Foo foo;
std::future<void> future = runAsyncTerminateOnException(&Foo::print, &foo);
std::future<void> future2 = runAsyncTerminateOnException(&Foo::print2, &foo);
return 0;
}
See it live, with possible output.
I obviously copied the first closure instead of preforming the required step to move it into the second closure (as one would do in c++11). You can of course move it with a specific move capture in c++14.

In c++17, the clean way to do this will be to use std::invoke.
I have hacked it in here to demonstrate.
#include <iostream>
#include <future>
#include <functional>
#include <type_traits>
namespace std
{
template<class T>
static constexpr bool is_member_pointer_v = std::is_member_pointer<T>::value;
template<class T>
static constexpr bool is_function_v = std::is_function<T>::value;
template<class B, class T>
static constexpr bool is_base_of_v = std::is_base_of<B, T>::value;
namespace detail {
template <class T>
struct is_reference_wrapper : std::false_type {};
template <class U>
struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {};
template <class T>
constexpr bool is_reference_wrapper_v = is_reference_wrapper<T>::value;
template <class Base, class T, class Derived, class... Args>
auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args)
noexcept(noexcept((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)))
-> std::enable_if_t<std::is_function_v<T> &&
std::is_base_of_v<Base, std::decay_t<Derived>>,
decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>
{
return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
}
template <class Base, class T, class RefWrap, class... Args>
auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args)
noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
-> std::enable_if_t<std::is_function_v<T> &&
is_reference_wrapper_v<std::decay_t<RefWrap>>,
decltype((ref.get().*pmf)(std::forward<Args>(args)...))>
{
return (ref.get().*pmf)(std::forward<Args>(args)...);
}
template <class Base, class T, class Pointer, class... Args>
auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args)
noexcept(noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
-> std::enable_if_t<std::is_function_v<T> &&
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>
{
return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
}
template <class Base, class T, class Derived>
auto INVOKE(T Base::*pmd, Derived&& ref)
noexcept(noexcept(std::forward<Derived>(ref).*pmd))
-> std::enable_if_t<!std::is_function_v<T> &&
std::is_base_of_v<Base, std::decay_t<Derived>>,
decltype(std::forward<Derived>(ref).*pmd)>
{
return std::forward<Derived>(ref).*pmd;
}
template <class Base, class T, class RefWrap>
auto INVOKE(T Base::*pmd, RefWrap&& ref)
noexcept(noexcept(ref.get().*pmd))
-> std::enable_if_t<!std::is_function_v<T> &&
is_reference_wrapper_v<std::decay_t<RefWrap>>,
decltype(ref.get().*pmd)>
{
return ref.get().*pmd;
}
template <class Base, class T, class Pointer>
auto INVOKE(T Base::*pmd, Pointer&& ptr)
noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd))
-> std::enable_if_t<!std::is_function_v<T> &&
!is_reference_wrapper_v<std::decay_t<Pointer>> &&
!std::is_base_of_v<Base, std::decay_t<Pointer>>,
decltype((*std::forward<Pointer>(ptr)).*pmd)>
{
return (*std::forward<Pointer>(ptr)).*pmd;
}
template <class F, class... Args>
auto INVOKE(F&& f, Args&&... args)
noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
-> std::enable_if_t<!std::is_member_pointer_v<std::decay_t<F>>,
decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
{
return std::forward<F>(f)(std::forward<Args>(args)...);
}
} // namespace detail
template< class F, class... ArgTypes >
auto invoke(F&& f, ArgTypes&&... args)
// exception specification for QoI
noexcept(noexcept(detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...)))
-> decltype(detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...))
{
return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
}
}
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
return std::async(std::launch::async, [=]() -> decltype(auto) {
try {
return std::invoke(fn, args...);
} catch (...) {
std::cout << "Terminate Called!" << std::endl;
std::terminate();
}
});
}
struct Foo {
void print() {
printf("Foo::print()\n");
}
void print2() {
printf("Foo::print2()\n");
throw 1;
}
};
int main() {
Foo foo;
std::future<void> future = runAsyncTerminateOnException(&Foo::print, &foo);
std::future<void> future2 = runAsyncTerminateOnException(&Foo::print2, &foo);
return 0;
}
error when invoking templated member function:
The error is this <source>: In instantiation of 'runAsyncTerminateOnException(Fn&&, Args&& ...)::<lambda()> [with Fn = void (Foo::*)(int&&); Args = {Foo*, int}]':
implying that Foo::print is demanding an int&& of course it is. That's what you wrote:
void print(Args&&... args)
It's not reasonable for a print function to demand ownership of objects. Declare it as it should be:
struct Foo {
template<class... Args>
void print(const Args&... args) {
printf("Foo::print(%d)\n", args...);
}
};

I found the solution for c++17.
It works only if we do not use auto for the return type of runTerminateOnException().
template<class Fn, class... Args>
inline std::result_of_t<Fn&&(Args&&...)> runTerminateOnException(Fn&& fn, Args&&... args) {
try {
return std::invoke(std::forward<Fn>(fn), std::forward<Args>(args)...);
} catch (...) {
std::terminate();
}
}
template<class Fn, class... Args>
inline auto runAsyncTerminateOnException(Fn&& fn, Args&&... args) {
return std::async(std::launch::async, runTerminateOnException<Fn, Args&&...>, std::forward<Fn>(fn), std::forward<Args>(args)...);
}

Related

Encapsulating arguments of variadic function in a class instance

Here some code with holes:
template<typename... Args>
class A
{
typedef function_type = void(*)(Args...);
public:
void set_args(Args&& ... args)
{
// something magic manages to encapsulate
// args in instance of A
}
void apply_args(function_type function)
{
// something magic manages to "retrieve"
// the encapsulated args
function(std::forward<Args>(args)...);
}
};
Would that be somehow possible ?
You can store your template arguments in class data member of std::tuple type and the use std::apply in order to apply stored arguments to provided function.
So, let's say you have an Action class like this:
template <typename... Args>
class Action {
std::tuple<Args...> args_;
public:
Action() = default;
Action(Args&&... args)
: args_(std::forward<Args>(args)...)
{}
void args(Args&&... args) {
args_ = std::make_tuple<Args...>(std::forward<Args>(args)...);
}
template <typename F>
void apply(F&& fun) {
std::apply(std::forward<F&&>(fun), args_);
}
};
where you set arguments through constructor Action action(1, 2, 3); or through separate function action.set(3, 2, 1);.
Then your main function can look like this:
int main() {
Action action(1, 2);
action.apply([](int a, int b) {
std::cout << "a + b = " << (a + b) << std::endl;
});
return 0;
}
Check live example
You can make use of std::tuple and std::apply
#include <iostream>
#include <tuple>
#include <functional>
#include <string>
template <typename... Ts>
class A
{
private:
std::function<void (Ts...)> f;
std::tuple<Ts...> args;
public:
template <typename F>
A(F&& func, Ts&&... args)
: f(std::forward<F>(func)),
args(std::make_tuple(std::forward<Ts>(args)...))
{}
void Invoke()
{
std::apply(f, args);
}
};
template <typename F, typename... Args>
A<Args...> Create(F&& f, Args&&... args)
{
return A<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
int main()
{
auto helloWorld = Create([] (std::string a, std::string b) { std::cout << a << ", " << b; }, std::string("Hello"), std::string("World!"));
helloWorld.Invoke();
}

Storing return values of functions in a tuple

Consider
#include <tuple>
template <typename... F>
auto execute (F... f) {
return std::make_tuple(f(0)...);
}
int foo(int) { return 5; }
int bar(int) { return 3; }
int main() {
auto tuple = execute(foo, bar);
}
What is a good workaround so that bar can return void?
I tried this, but it won't compile:
#include <tuple>
struct Void { };
template <typename T>
T check(T n) { return n; }
Void check(void) { return Void{}; }
template <typename... F>
auto execute (F... f) {
return std::make_tuple(check(f(0))...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar);
}
Update: I have a tentative solution, but it only works if we know that the arguments passed is always int 0. I'll try to make it work in any general setting. Or perhaps use std::optional like Steve suggested.
#include <tuple>
#include <type_traits>
struct Void { };
template <typename F>
auto execute_h (F f, std::enable_if_t<!std::is_void_v<std::result_of_t<F(int)>>>* = nullptr) {
const auto result = f(0);
return result;
}
template <typename F>
auto execute_h (F f, std::enable_if_t<std::is_void_v<std::result_of_t<F(int)>>>* = nullptr) {
f(0);
return Void{};
}
template <typename... F>
auto execute (F... f) {
return std::make_tuple(execute_h(f)...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar);
}
With abusing overload of operator , (as void(), T won't call custom operator,):
#include <tuple>
struct Void {};
template <typename T>
T&& operator , (T&& t, Void) { return std::forward<T>(t); }
template <typename... Fs>
auto execute (Fs... fs) {
return std::make_tuple((f(0), Void{})...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar); // tuple<int, Void>
}
You can use std::enable_if and a wrapper function to return a Void object for functors that return void:
#include <tuple>
#include <type_traits>
struct Void { };
template <typename Func, typename... Args>
auto check(Func func, Args&&... args)
-> std::enable_if_t<!std::is_void<decltype(func(std::forward<Args>(args)...))>::value, decltype(func(std::forward<Args>(args)...))>
{
return func(std::forward<Args>(args)...);
}
template <typename Func, typename... Args>
auto check(Func func, Args&&... args)
-> std::enable_if_t<std::is_void<decltype(func(std::forward<Args>(args)...))>::value, Void>
{
func(std::forward<Args>(args)...); return Void{};
}
template <typename... F>
auto execute (F... f) {
return std::make_tuple(check(f, 0)...);
}
int foo(int) { return 5; }
void bar(int) { }
int main() {
auto tuple = execute(foo, bar);
}
Live demo
It's a bit repetitive, but it gets the job done for any type of functor, any argument list, and any return type.
It's worth noting that there's a proposal floating around to make void a regular type that would let you avoid all of these hassles, but I'm not sure what the status of that is or if it will ever be accepted.

How to Deduce Argument List from Function Pointer?

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;
}

Wrapping a templated function call in a lambda

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());
}

Call a function with variadic arguments using parameter pack expansion, but modify th i-th parameter

Suppose we have a function
template<typename T, typename... Args>
T f(Args... args);
and we want to call f in an other function
template<typename... Args>
void bar(Args... args) {
// f(args1, ..., args(i-1), "modified argsi", args(i+1), ..., argsn);
}
and modify the i-th argument (and leave the other arguments untouched) for all i = 1, ..., n. f will return a result and I want to store all n results in a valarray.
How can we do that?
With I a compile time value, you may do:
namespace detail
{
template<std::size_t I>
struct impl
{
template <typename TUPLE>
auto operator() (TUPLE&& t) { return std::get<I>(t); }
};
template<>
struct impl<2>
{
template <typename TUPLE>
auto operator() (TUPLE&& t) { return std::get<2>(t) + 40; }
};
template <std::size_t... Is, typename TUPLE>
void bar(std::index_sequence<Is...>, TUPLE&& Tuple) {
return f(impl<Is>{}(std::forward<TUPLE>(Tuple))...);
}
}
template<typename... Args>
void bar(Args... args) {
detail::bar(std::index_sequence_for<Args...>(), std::forward_as_tuple(args...));
}
Live Demo
With i a runtime value:
namespace detail
{
template<class T>
auto modifier(T&& arg, std::size_t i, std::size_t pos) {
if (i == pos)
return arg + 40; // Or appropriate modification.
else
return std::forward<T>(arg);
}
template <std::size_t... Is, typename... Args>
void bar(std::size_t pos, std::index_sequence<Is...>, Args&&... args) {
return f(modifier(std::forward<Args>(args), Is, pos)...);
}
}
template<typename... Args>
void bar(std::size_t pos, Args&&... args) {
detail::bar(pos, std::index_sequence_for<Args...>(), std::forward<Args>(args)...);
}
Live Demo
Well, a lookup table does the job, if branching is to be avoided. Rough sketch:
#include <tuple>
#include <utility>
#include <iostream>
void foo(std::string a, std::string b, std::string c) {
std::cout << a << '|' << b << '|' << c;
}
template <typename, typename> struct passerAux;
template <std::size_t... prevI, std::size_t... followI>
struct passerAux<std::index_sequence<prevI...>, std::index_sequence<followI...>> {
template <typename... Args>
static decltype(auto) passer( Args&&... args ) {
auto tuple = std::forward_as_tuple(std::forward<Args>(args)...);
return foo( std::forward<std::tuple_element_t<prevI, decltype(tuple)>>(std::get<prevI>(tuple))...,
"ModifiedArg",
std::forward<std::tuple_element_t<followI+sizeof...(prevI)+1, decltype(tuple)>>(std::get<followI+sizeof...(prevI)+1>(tuple))... );
}
};
template <typename... Args, std::size_t... indices>
decltype(auto) passer( std::size_t i, std::index_sequence<indices...>, Args&&... args ) {
void(*lookup[])(Args&&...) {
passerAux<std::make_index_sequence<indices>, std::make_index_sequence<sizeof...(Args)-indices-1>>::passer...
};
return lookup[i](std::forward<Args>(args)...);
}
template <typename... Args>
decltype(auto) passer( std::size_t i, Args&&... args ) {
return passer(i, std::make_index_sequence<sizeof...(Args)>{}, std::forward<Args>(args)... );
}
int main() {
passer(0, "A", "B", "C"); std::cout << '\n';
passer(1, "A", "B", "C"); std::cout << '\n';
passer(2, "A", "B", "C");
}
Demo.
Based on your comments, I think (?) you want something like:
namespace detail {
template <typename Arg, typename Idx>
auto modify_arg(Arg&& arg, Idx )
{
// TODO: whatever modifications you want to make
// to the argument indexed by Idx
}
template <size_t... Is, typename... Args>
void bar(std::index_sequence<Is...>, Args&&... args)
{
// Don't know where 'T' comes from - you still
// need that for your f()
f(modify_arg(std::forward<Args>(args),
std::integral_constant<size_t, Is>{})...
);
}
}
template<typename... Args>
void bar(Args&&... args) {
detail::bar(std::index_sequence_for<Args...>{},
std::forward<Args>(args)...
);
}
A non compile time implementation might be:
#include <iostream>
#include <type_traits>
// Replace a value at a position
// =============================
template<typename R>
struct Replace {
int i;
R replacement;
Replace(int i, R&& replacement)
: i(i), replacement(replacement)
{}
template<typename T>
T&& operator() (T&& value) noexcept {
return (0 == i--)
? std::forward<T>(replacement)
: std::forward<T>(value);
}
};
template <typename R, typename... Args>
Replace<R> replace(int i, R&& replacement) {
return Replace<R>(i, std::forward<R>(replacement));
}
// Test: Print values
// ==================
template<typename T, typename... Args>
void print(const T&, const Args&...);
template<typename T, typename... Args>
void print(const T& value) {
std::cout << value << '\n';
}
template<typename T, typename... Args>
void print(const T& value, const Args&... args) {
std::cout << value << '\n';
print(args...);
}
// Test: Function
// ==============
template<typename... Args>
void f(Args... args) {
// Note, 'print(replace(1, 7)(args)...);' will not work.
auto r = replace(1, 7);
print(r(args)...);
}
int main()
{
f(1, 2, 3);
}