Unpack variadic parameters for a template template function? - c++

// some arbitrary function
template<typename T>
void log( T&& obj )
{
std::cout << obj << std::endl;
}
// arbitrary transformation
template<typename T>
T convert(T&& obj) {
return obj;
}
template<template <typename> typename F, typename... T>
void callOn( F<T> func, /// issue: what's the type of func?
T&&... params)
{
func(std::forward<T>(convert(std::forward<T>(params)))...);
}
int main()
{
callOn(log, -1, -2.0);
return 0;
}
Is this possible at all?
Compiler complains: no matching function for call to 'callOn(, ..>). Why ?
Update: suppose log is not unary function
template<typename T>
void log(T&& value) { std::cout << value << std::endl; }
template<typename First, typename... Rest>
void log(First&& f, Rest&&... rest)
{
std::cout << f << ",";
log(std::forward<Rest>(rest)...);
}
callOn takes type "template " which doesn't match the type of log? How to specify the type of func?

Use a function object. Here's a compilable example:
#include <utility>
#include <iostream>
struct Log
{
template<typename T> void operator()(T&& t) {
std::cout << t << std::endl;
}
template<typename T, typename... Rest> void operator()(T&& t, Rest&&... rest)
{
std::cout << t << ", ";
(*this)(std::forward<Rest>(rest)...);
}
};
template<typename T>
T convert(T&& obj) {
return obj;
}
template<typename F, typename... T>
void callOn(F funcobj, T&&... params)
{
funcobj(std::forward<T>(convert(std::forward<T>(params)))...);
}
int main()
{
callOn(Log(), -1, -2.17, "abc");
return 0;
}

I don't think the syntax of template <typename> typename F is correct, and Standard specified in 14.3.3/1 that "A template-argument for a template template-parameter shall be the name of a class template or an alias template", not a function template. If you want to pass a function template, you can declare the parameter as a pointer to function:
template<typename... T>
void callOn( void (*func)(T&&...params),
T&&... params)
{
//same as before
}
And when callOn(log, -1, -2.0); is called, the type of T is not deduced from log but from {-1, -2.0} to be {int, double}, then func is initialized from the pointer pointed to log<int, double>(int&&, double&&).

Related

add to queue a template function c++

i search on google how to store and to execute functions (template function or not) passing in queue but i didn't find an enough good answer...
this is my code
Window.h
struct QueueEventFunction {
std::vector<std::function<void()>> v; // stores the functions and arguments
// as zero argument lambdas
template <typename F,/*template <typename U, typename = std::allocator<U> >*/ typename ...Args>
void Enqueue(F (*f), Args... args)
{
v.push_back([=] { f(args...); }); // add function and arguments
// as zero argument lambdas
// that capture the function and arguments
}
void CallAll()
{
for (auto f : v)
f(); // calls all the functions
}
};
class Window : public sf::RenderWindow {
public:
Window(sf::VideoMode window, const std::string& title, sf::Uint32 style = 7U, sf::ContextSettings settings = sf::ContextSettings());
~Window();
template <typename F, /*template <typename ...U > */typename ...Args>
void addQueue(F (*f), Args...args);
void execQueue();
private:
QueueEventFunction queue;
}
template <typename F, /*template <typename ...U >*/ typename ...Args>
void Window::addQueue(F (*f), Args...args) {
queue.Enqueue(f, std::forward<Args>(args)...);
}
void Window::execQueue() {
queue.CallAll();
}
TestWindow.cpp
template<typename T>
void add(T a, T b) {
return a + b;
}
class foo{
public:
template<typename T> T add( T a, T b){ return a+ b;}
};
int main() {
Window window(sf::VideoMode(600, 600), "Test Window",7U,sf::ContextSettings());
window.addQueue(add<int>,1,2); // doesn't work
foo bar;
window.addQueue(&foo::add<int>,1,2); // doesn"t work
window.addQueue(bar.add<int>(1,2)); // doesn"t work
return 0;
}
i got a external symbol error.
and if i put a function member class it simply doesn't work. (compilation error)
have you got an idea to correctly make the function addQueue<> with args ?
The big problem with your code is that you take the function pointer as a pointer
template <typename F, typename ...Args>
void Enqueue(F (*f), Args... args)
and
template <typename F, typename ...Args>
void addQueue(F (*f), Args...args);
What you really want is
template <typename F, typename ...Args>
void Enqueue(F f, Args... args)
and
template <typename F, typename ...Args>
void addQueue(F f, Args...args);
And then you can pass any callable thing. Then you can use it with results of bind, lambdas, class member functions, class static member functions, and normal functions.
Then you can use it like
template<typename T>
int add(T a, T b) {
std::cout << "add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
class foo{
public:
template<typename T>
T add( T a, T b) {
std::cout << "foo::add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
template<typename T>
static T static_add( T a, T b) {
std::cout << "foo::static_add(" << a << "," << b << ") -> " << a+b << "\n";
return a + b;
}
};
int main() {
Window window(sf::VideoMode(600, 600),"Test Window",7U,sf::ContextSettings());
foo bar;
auto bar_add = [&bar](auto a,auto b){ return bar.add<int>(a,b); };
auto bind_add = std::bind(&foo::add<int>, &bar, std::placeholders::_1, std::placeholders::_2);
window.addQueue(bind_add,5,2);
window.addQueue(bar_add,5,2);
window.addQueue(add<int>,5,2);
window.addQueue(foo::static_add<int>,5,2);
window.execQueue();
return 0;
}
Try it here https://www.onlinegdb.com/t9WczrL-c

c++ : how to remove cv-qualifiers of a type to access class functions?

Here an example:
#include <iostream>
template<typename T,
typename ... Args>
void print(T&& t, Args&& ... args)
{
// line where compilation fails when the A::run is called
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
{
t.display(std::forward<Args>(args)...);
}
else
{
std::cout << "not applicable !" << std::endl;
}
}
template<typename T>
class A
{
public:
A(T&& t):t_(t){}
template <typename... Args>
void run(Args&& ... args)
{
print<T,Args...>(t_,std::forward<Args>(args)...);
}
T t_;
};
template <typename T> A(T&) -> A<T&>;
template <typename T> A(T&&) -> A<T>;
class B
{
public:
B(int value):value_(value){}
void display(int a, int b)
{
std::cout << value_ << " "
<< a << " "
<< b << std::endl;
}
int value_;
};
int main()
{
int v1=10;
int v2=20;
B b1{1};
A a1{b1};
a1.t_.display(v1,v2);
A a2{B(2)};
a2.t_.display(v1,v2);
//a1.run(v1,v2); // (1)
//a2.run(v1,v2); // (2)
//a1.run(v1);
return 0;
}
The code above compiles and runs fine. But if the 3 last lines (calls to run()) are un-commented, the following compilation error occurs:
(1)
main.cpp:7:48: error: ‘display’ is not a member of ‘B&’
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
(2)
main.cpp:27:25: error: no matching function for call to ‘print(B&, int&, int&)’
print<T,Args...>(t_,std::forward<Args>(args)...);
Note :
template <typename T> A(T&) -> A<T&>;
template <typename T> A(T&&) -> A<T>;
explained here:
c++ copy (reference) constructor and move constructor of class cohabitation
Problem (1) and (2) are different problems.
Problem (1) come from the fact that in the following std::is_invocable_v
template<typename T,
typename ... Args>
void print(T&& t, Args&& ... args)
{
if constexpr (std::is_invocable_v<decltype(&T::display),T*,Args...>)
// no T but std::decay_t<T> ...............^...........^
instead of T (that can be a reference) you need the "decayed" type
I propose
template <typename T, typename ... Args>
void print (T && t, Args && ... args)
{
using U = std::decay_t<T>;
if constexpr ( std::is_invocable_v<decltype(&U::display), U*, Args...> )
t.display(std::forward<Args>(args)...);
else
std::cout << "not applicable !" << std::endl;
}
Problem (2) come from the fact that explicating the template parameters in the following print() call
template <typename... Args>
void run(Args&& ... args)
{
print<T,Args...>(t_,std::forward<Args>(args)...);
}
you impede the correct template deduction.
Suggestion: let template deduction, and perfect forwarding, works and call the function as follows
print(t_,std::forward<Args>(args)...);

Is there a way to partially match a variadic template parameter pack?

I currently have a system to "connect" signals to functions. This signal is a variadic template that has as template parameters the arguments of the functions it can connect to.
In the current implementation, I obviously cannot connect to functions whose arguments aren't exactly the same (or those that can be converted to) as the signal's parameters. Now, as I'm trying to mimic Qt's signal/slot/connect, I'd also like to connect a signal of N parameters to a slot of M<N parameters, which is perfectly well-defined (i.e. ignore the >M parameters of the signal and just pass the first M to the connected function). For an example of the code I have in its most simplistic form, see Coliru.
So the question is two-fold:
How do I make the connect call work for a function void g(int);?
How do I make the emit call work for a function void g(int);?
I'm guessing I'll have to make some "magic" parameter pack reducer for both the slot and its call function, but I can't see how it all should fit together so it's quite hard to actually start trying to code a solution. I'm OK with a C++17-only solution, if at least Clang/GCC and Visual Studio 2015 can compile it.
The code linked above for completeness:
#include <memory>
#include <vector>
template<typename... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template<typename Callable, typename... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
callable_slot(Callable callable) : callable(callable) {}
void call(ArgTypes... args) const override { callable(args...); }
Callable callable;
};
template<typename... ArgTypes>
struct signal
{
template<typename Callable>
void connect(Callable callable)
{
slots.emplace_back(std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{
for(const auto& slot : slots)
{
slot->call(args...);
}
}
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f(int, char) {}
int main()
{
signal<int, char> s;
s.connect(&f);
s.emit(42, 'c');
}
template<class...> struct voider { using type = void; };
template<class... Ts> using voidify = typename voider<Ts...>::type;
template<class C, class...Args>
using const_lvalue_call_t = decltype(std::declval<const C&>()(std::declval<Args>()...));
template<class T, std::size_t...Is>
auto pick_from_tuple_impl(T &&, std::index_sequence<Is...>)
-> std::tuple<std::tuple_element_t<Is, T>...>;
template<class Tuple, class = std::enable_if_t<(std::tuple_size<Tuple>::value > 0)>>
using drop_last = decltype(pick_from_tuple_impl(std::declval<Tuple>(),
std::make_index_sequence<std::tuple_size<Tuple>::value - 1>()));
template<class C, class ArgsTuple, class = void>
struct try_call
: try_call<C, drop_last<ArgsTuple>> {};
template<class C, class...Args>
struct try_call<C, std::tuple<Args...>, voidify<const_lvalue_call_t<C, Args...>>> {
template<class... Ts>
static void call(const C& c, Args&&... args, Ts&&... /* ignored */) {
c(std::forward<Args>(args)...);
}
};
Then in callable_slot:
void call(ArgTypes... args) const override {
using caller = try_call<Callable, std::tuple<ArgTypes...>>;
caller::call(callable, std::forward<ArgTypes>(args)...);
}
For member pointer support (this requires SFINAE-friendly std::result_of), change const_lvalue_call_t to
template<class C, class...Args>
using const_lvalue_call_t = std::result_of_t<const C&(Args&&...)>;
then change the actual call in try_call::call to
std::ref(c)(std::forward<Args>(args)...);
This is poor man's std::invoke for lvalue callables. If you have C++17, just use std::invoke directly (and use std::void_t instead of voidify, though I like the sound of the latter).
Not sure to understand what do you exactly want but... with std::tuple and std::make_index_sequence ...
First of all you need a type traits that give you the number of arguments of a function (or std::function)
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
Next you have to add a constexpr value in callable_slot to memorize the number of arguments in the Callable function
static constexpr std::size_t numA { numArgs<Callable>::value };
Then you have to modify the call() method to pack the arguments in a std::tuple<ArgTypes...> and call another method passing the tuple and an index sequence from 0 to numA
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Last you have to call, in CallI(), the callable() function with only the first numA elements of the tuple of arguments
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
The following is a full working example
#include <memory>
#include <vector>
#include <iostream>
#include <functional>
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename ... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template <typename Callable, typename ... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
static constexpr std::size_t numA { numArgs<Callable>::value };
callable_slot(Callable callable) : callable(callable)
{ }
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Callable callable;
};
template <typename ... ArgTypes>
struct signal
{
template <typename Callable>
void connect(Callable callable)
{
slots.emplace_back(
std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{ for(const auto& slot : slots) slot->call(args...); }
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f (int i, char c)
{ std::cout << "--- f(" << i << ", " << c << ")" << std::endl; }
void g (int i)
{ std::cout << "--- g(" << i << ")" << std::endl; }
struct foo
{
static void j (int i, char c)
{ std::cout << "--- j(" << i << ", " << c << ")" << std::endl; }
void k (int i)
{ std::cout << "--- k(" << i << ")" << std::endl; }
};
int main ()
{
std::function<void(int, char)> h { [](int i, char c)
{ std::cout << "--- h(" << i << ", " << c << ")" << std::endl; }
};
std::function<void(int)> i { [](int i)
{ std::cout << "--- i(" << i << ")" << std::endl; }
};
using std::placeholders::_1;
foo foo_obj{};
std::function<void(int)> k { std::bind(&foo::k, foo_obj, _1) };
signal<int, char> s;
s.connect(f);
s.connect(g);
s.connect(h);
s.connect(i);
s.connect(foo::j);
s.connect(k);
s.emit(42, 'c');
}
This example need C++14 because use std::make_index_sequence and std::index_sequence.
Substitute both of they and prepare a C++11 compliant solution isn't really difficult.

Fallback function using ellipsis: can we force the size of the parameters pack?

Consider the following code:
#include <utility>
#include <iostream>
struct S {
template<typename T, typename... A>
auto f(A&&... args) -> decltype(std::declval<T>().f(std::forward<A>(args)...), void()) {
std::cout << "has f(int)" << std::endl;
}
template<typename>
void f(...) {
std::cout << "has not f(int)" << std::endl;
}
};
struct T { void f(int) { } };
struct U { };
int main() {
S s;
s.f<T>(42); // -> has f(int)
s.f<U>(42); // -> has not f(int)
// oops
s.f<T>(); // -> has not f(int)
}
As shown in the example the third call to f works just fine, even if the number of arguments is wrong, for it's not wrong at all for the fallback function.
Is there a way to force the number of arguments when an ellipsis is involved that way?
I mean, can I check at compile time that the size of the arguments list is exactly 1, no matter if the main function or the fallback is chosen?
Good solutions are also the ones that only involves the first template function and result in hard-errors instead of soft-errors because of the size of the parameter pack.
Of course, it can be solved with several techniques without using variadic arguments. As an example: int/char dispatching on internal template methods; explicitly specify the arguments list; whatever...
The question is not about alternative approaches to do that, I already know them.
It's just to know if I'm missing something basic here or it's not possible and that's all.
If I understand correctly your issue, you may add a layer:
struct S {
private:
template<typename T, typename... A>
auto f_impl(A&&... args)
-> decltype(std::declval<T>().f(std::forward<A>(args)...), void()) {
std::cout << "has f(int)" << std::endl;
}
template<typename>
void f_impl(...) {
std::cout << "has not f(int)" << std::endl;
}
public:
template<typename T, typename A>
auto f(A&& args) { return f_impl<T>(std::forward<A>(arg)); }
};
With traits, you may do
template <typename T, typename ... Ts>
using f_t = decltype(std::declval<T>().f(std::declval<Ts>()...));
template <typename T, typename ... Ts>
using has_f = is_detected<f_t, T, Ts...>;
struct S {
template<typename T, typename... A>
std::enable_if_t<has_f<T, A&&...>::value && sizeof...(A) == 1> f(A&&... args)
{
std::cout << "has f(int)" << std::endl;
}
template<typename T, typename... A>
std::enable_if_t<!has_f<T, A&&...>::value && sizeof...(A) == 1> f(A&&... args) {
std::cout << "has not f(int)" << std::endl;
}
};
Demo
You can use a function (assert) that gets pointer to a function to deduce size of paramemters :
#include <utility>
#include <iostream>
template <typename...Args>
struct size_assert{
template <typename T,typename R,typename... Params>
constexpr static bool assert(R(T::*)(Params...) )
{
static_assert(sizeof...(Args) == sizeof...(Params),"Incorrect size of arguments!");
return true;
}
};
struct S {
template<typename T, typename... A, bool = size_assert<A...>::assert(&T::f)>
auto f(A&&... args) -> decltype(std::declval<T>().f(std::forward<A>(args)...), void())
{
std::cout << "has f(int)" << std::endl;
}
template<typename>
void f(...) {
std::cout << "has not f(int)" << std::endl;
}
};
struct T { void f(int) { } };
struct U { };
int main() {
// std::cout <<fc(&f);
S s;
s.f<T>(42); // -> has f(int)
s.f<U>(42); // -> has not f(int)
// oops
s.f<T>(); // -> has not f(int)
}

How to call conditionally B::f only if derived from B in C++11?

In case when static polymorphism is used, especially in templates (e.g. with policy/strategy pattern), it may be required to call base function member, but you don't know was instantiated class actually derived from this base or not.
This easily can be solved with old good C++ ellipsis overload trick:
#include <iostream>
template <class I>
struct if_derived_from
{
template <void (I::*f)()>
static void call(I& x) { (x.*f)(); }
static void call(...) { }
};
struct A { void reset() { std::cout << "reset A" << std::endl; } };
struct B { void reset() { std::cout << "reset B" << std::endl; } };
struct C { void reset() { std::cout << "reset C" << std::endl; } };
struct E: C { void reset() { std::cout << "reset E" << std::endl; } };
struct D: E {};
struct X: A, D {};
int main()
{
X x;
if_derived_from<A>::call<&A::reset>(x);
if_derived_from<B>::call<&B::reset>(x);
if_derived_from<C>::call<&C::reset>(x);
if_derived_from<E>::call<&E::reset>(x);
return 0;
}
The question is:
Is there any better simple way (e.g. SFINAE doesn't look so) to achieve same result in C++11/C++14?
Would empty call of ellipsis parameter function be elided by optimizing compiler? Hope such case is not special against any "normal" function.
One option is to introduce two overloads of different priorities and to equip the preferred one with an expression SFINAE.
#include <utility>
template <typename T, typename... Args, typename C, typename R, typename... Params>
auto call_impl(int, R(C::*f)(Args...), T&& t, Params&&... params)
-> decltype((std::forward<T>(t).*f)(std::forward<Params>(params)...))
{
return (std::forward<T>(t).*f)(std::forward<Params>(params)...);
}
template <typename T, typename... Args, typename C, typename R, typename... Params>
void call_impl(char, R(C::*)(Args...), T&&, Params&&...)
{
}
template <typename T, typename... Args, typename C, typename R, typename... Params>
auto call(R(C::*f)(Args...), T&& t, Params&&... params)
-> decltype(call_impl(0, f, std::forward<T>(t), std::forward<Params>(params)...))
{
return call_impl(0, f, std::forward<T>(t), std::forward<Params>(params)...);
}
Test:
int main()
{
X x;
call(&B::reset, x);
}
DEMO
The upper function will be selected first by overload resolution (due to an exact match of 0 against int), and possibly excluded from the set of viable candidates if (t.*f)(params...) is not valid. In the latter case, the call to call_impl falls back to the second overload, which is a no-op.
Given that &A::reset may fail for multiple reasons, and you may not necessarily want to explicitly specify the function's signature, and, on top of that, you want the call to fail if the member function exists, but it does not match function call arguments, then you can exploit generic lambdas:
#include <utility>
#include <type_traits>
template <typename B, typename T, typename F
, std::enable_if_t<std::is_base_of<B, std::decay_t<T>>{}, int> = 0>
auto call(T&& t, F&& f)
-> decltype(std::forward<F>(f)(std::forward<T>(t)))
{
return std::forward<F>(f)(std::forward<T>(t));
}
template <typename B, typename T, typename F
, std::enable_if_t<!std::is_base_of<B, std::decay_t<T>>{}, int> = 0>
void call(T&& t, F&& f)
{
}
Test:
int main()
{
X x;
call<A>(x, [&](auto&& p) { return p.A::reset(); });
call<B>(x, [&](auto&& p) { return p.B::reset(); });
}
DEMO 2
what about something like:
#include <iostream>
#include <type_traits>
struct A { void reset() { std::cout << "reset A" << std::endl; } };
struct B { void reset() { std::cout << "reset B" << std::endl; } };
struct X :public A{};
template <typename T, typename R, typename BT>
typename std::enable_if<std::is_base_of<BT, T>::value, R>::type
call_if_possible(T & obj, R(BT::*mf)())
{
return (obj.*mf)();
}
template <typename T, typename R, typename BT>
typename std::enable_if<!std::is_base_of<BT, T>::value, R>::type
call_if_possible(T & obj, R(BT::*mf)()) { }
int main()
{
X x;
call_if_possible(x, &A::reset);
call_if_possible(x, &B::reset);
}
ideone
edit
maybe more readable way:
template <typename T, typename R, typename BT>
R call_if_possible_impl(T & obj, R(BT::*mf)(), std::false_type){}
template <typename T, typename R, typename BT>
R call_if_possible_impl(T & obj, R(BT::*mf)(), std::true_type)
{
return (obj.*mf)();
}
template <typename T, typename R, typename BT>
R call_if_possible(T & obj, R(BT::*mf)())
{
return call_if_possible_impl(obj, mf, typename std::is_base_of<BT, T>::type());
}
ideone
Basing on previously provided answers by #PiotrSkotnicki and #relaxxx I would like to combine the most simple and readable solution, without SFINAE and other blood-from-the-eyes things. It's just for reference, will not be accepted anyway:
#include <iostream>
#include <type_traits>
template <class Base, class Derived>
using check_base = typename std::is_base_of<Base, Derived>::type;
template <class Base, class Derived, typename Func>
void call(Derived& d, Func&& f)
{
call<Base>(d, std::forward<Func>(f), check_base<Base, Derived>());
}
template <class Base, typename Func>
void call(Base& b, Func&& f, std::true_type)
{
f(b);
}
template <class Base, class Derived, typename Func>
void call(Derived&, Func&&, std::false_type)
{
}
struct A { void reset(int i) { std::cout << "reset A: " << i << std::endl;} };
struct B { void reset() { std::cout << "reset B" << std::endl;} };
struct C { void reset() { std::cout << "reset C" << std::endl;} };
struct E: C { void reset() { std::cout << "reset E" << std::endl;} };
struct D: A, E {};
int main()
{
D d;
int i = 42;
call<A>(d, [&](auto& p) { p.reset(i); } );
call<B>(d, [](auto& p) { p.reset(); } );
call<C>(d, [](auto& p) { p.reset(); } );
call<E>(d, [](auto& p) { p.reset(); } );
}
Live at: http://cpp.sh/5tqa