Template Deduction of Base Template Parameters through Smart Pointers and Conversion - c++

See Compiler Explorer for a full example: https://godbolt.org/z/_rVFvO
Given an abstract template class Runnable and an implementation Derived inheriting from Runnable<int>:
#include <iostream>
#include <memory>
using namespace std;
template<class... Args>
struct Runnable
{
virtual ~Runnable() = default;
virtual void f(Args... args) const = 0;
};
struct Derived : public Runnable<int>
{
void f(int x) const override
{
cout << "f(" << x << ")" << endl;
}
};
What is the underlying reason the template parameter deduction for the function accept_variadic fails given the smart pointer to a derived type?
template<class... Args>
void accept_variadic(std::unique_ptr<Runnable<Args...>> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
int main()
{
accept_variadic(make_unique<Derived>(), 5); // Error (no conversion)
return 0;
}
But given a reference (or pointer) directly without a smart pointer works:
template<class... Args>
void accept_variadic_ref(const Runnable<Args...>& o, Args&&... args)
{
o.f(forward<Args>(args)...);
}
int main()
{
accept_variadic_ref(Derived(), 5); // OK
return 0;
}
Also, is there a way to support a similar usage with template class deduction guides or using a different smart pointer (owning raw pointers and non lifetime extending references would be difficult in my application).

Instead of:
template<class... Args>
void accept_variadic(std::unique_ptr<Runnable<Args...>> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
You can use TMP to get what you want:
template<class T, class... Args>
std::enable_if_t<std::is_convertible_v<std::unique_ptr<T>,
std::unique_ptr<Runnable<Args...>>>>
accept_variadic(std::unique_ptr<T> o, Args&&... args)
{
o->f(forward<Args>(args)...);
}
(See full code here)
This is not 100% equivalent, since the propose solution accepts a std::unique_ptr of the Derived type, while the original code will accept only the base type.
The original code does not work, since the templates do to match types that require conversion. In your code, the two std::unique_ptr types are not base/derived of each other, so the templates won't match.
With the proposed solution, the function accepts the original std::unique_ptr, provided that it can be converted to the base type inside the function. The std::enable_if_t makes sure that other types don't match, only the ones that can be converted to the base.
Edit
In some variants of the question, the original solution could be problematic. This can happen in question variants in which calling f() on a base class is treated differently than calling f() on the derived class. There are several possibilities when this can happen (but not in the original question). To overcome this risk, accept_variadic() should be altered to:
template<class T, class... Args>
std::enable_if_t<std::is_convertible_v<T&, Runnable<Args...>&>>
accept_variadic(std::unique_ptr<T> o, Args&&... args)
{
// could also be solved with
// std::unique_ptr<Runnable<Args...>> base = std::move(o);
Runnable<Args...> & runnable = *o;
runnable.f(forward<Args>(args)...);
}

Related

Member function template to call a funcion on a data member with arbitrary arguments

I'm working on a C++11 code base and wondering how I can call any function on a member type passing arbitrary arguments. Note that since I'm using C++11 I can't use something like std::invoke.
I started creating a function template in the Outer class, but my initial try gives me a compile error.
#include <iostream>
#include <utility>
#include <type_traits>
struct Inner {
void bar(int x) {
std::cout << "Called: x=" << x << std::endl;
}
};
struct Outer {
explicit Outer(Inner *i) : b{i} {}
void foo(int) {}
Inner* b;
template <typename Func, typename ... Args>
void CallInner(Func&& f, Args&& ... args) {
b->f(std::forward<Args>(args)...);
}
};
int main() {
Inner inner{};
Outer outer(&inner);
outer.CallInner(&Inner::bar, 5);
}
Try it out yourself
Again, I would like to keep the signature of the function CallInner unchanged from the above sample code.
Since f is a pointer a member function it needs to be dereferenced first before being called:
(b->*f)(std::forward<Args>(args)...);
You don't have much choice with regards to changing the signature, because at least one additional template is required.
The correct syntax is a little bit more complicated:
struct Outer {
explicit Outer(Inner *i) : b{i} {}
void foo(int) {}
Inner* b;
template <typename Ret, typename ...FuncArgs, typename ... Args>
void CallInner(Ret (Inner::*f)(FuncArgs...), Args&& ... args) {
(b->*f)(std::forward<Args>(args)...);
}
};
The first parameter to CallInner must be a method pointer, and, in a template context, it needs to be templated not just by a set of variadic template parameters, FuncArgs, but also its return type, Ret. Then you also need a second set of variadic template parameters for the forwarding references of the arguments you're forwarding (which may not necessarily be the same as FuncArgs, hence the need for a separate set of variadic template types).

Variadic Function That Calls Constructor With Given Arguments

Need to create variadic template<T> function with different arg types that will call constructor of T with given arguments, sort of like when creating a thread but reverse (when creating a thread, its constructor calls function at given funct pointer).
So in pseudo code it should look something like this
template<typename T>
T* CreateNew( ARGS ) {
return new T( ARGS ); //Constructor Gets Same Arguments That Were
} //Passed To The Function
Want this to behave like when creating threads, when they call functions with their arguments that are of different types (which I am unsure how to achive).
Its not entirely clear to me but I think you want to look up variadic templates, e.g.:
template <typename T, typename... Args>
T* CreateNew(Args... args) {
return new T(args...);
}
Adding Example:
#include <iostream>
class A {
public:
A(int a){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
A(std::string a){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
A(int a,std::string b){
std::cout<<__PRETTY_FUNCTION__<<std::endl;
}
};
template<typename T, typename... Args>
T* create(Args... args){
return new T(args...);
}
int main(){
A b(1);
A c("a");
A d(1,"a");
A* bp = create<A>(1);
A* cp = create<A>("a");
A* dp = create<A>(1,"a");
// This code leaks
return 0;
}
Note that because the changes are kept as minimal as possible, we still return a T* here as the original code. Most of the time, this is not a good idea since ownership is passed via raw pointers. Therefore, as suggested by the comments, you might want to use a std::unique_ptr, which would make your CreateNew function basically equivalent to std::make_unique.
The correct way to write this function is
template <typename T, typename... Args>
T* CreateNew(Args&&... args) {
return new T(std::forward<Args>(args)...);
}
Without the forwarding reference Args&& and without std::forward, the original value categories of the passed arguments will not be propagated to T's constructor, causing potential performance and semantic problems.

How to store and restore the exact type of a type-erased object?

I'm sure there's a name for what I'm looking for, I just don't know it (and if I did, I'd probably find the answer already). Basically, I want to implement my own lightweight version of std::function for sports. I want to initialize it with a lambda, and later invoke it. I can wrap the lambda with my template wrapper class, nothing to it:
struct CInvokableAbstract {
virtual ~CInvokableAbstract() = default;
};
template <class InvokableObject>
struct CInvokableBasic : public CInvokableAbstract
{
CInvokableBasic(InvokableObject&& target) : _invokable(std::move(target)) {}
template <typename... Args>
typename std::result_of<decltype(&InvokableObject::operator())(Args...)>::type operator()(Args... args) const
{
return _invokable(std::forward<Args>(args)...);
}
private:
InvokableObject _invokable;
};
Now I can make my class that's semantically similar to std::function, but how can I store the exact type of the lambda in order to convert the type-erased object back to its original concrete type?
struct CInvokableDeferred
{
template <class InvokableObject>
CInvokableDeferred(InvokableObject&& target) noexcept : _invokable(std::make_unique<CInvokableBasic<InvokableObject>>(std::move(target))) {}
template <typename... Args>
void operator()(Args... args) const
{
// How can I know the original concrete type to cast this to?
static_cast<???>(_invokable.get())->(std::forward<Args>(args)...);
}
private:
std::unique_ptr<CInvokableAbstract> _invokable;
};
I can't think of any template trickery that could do that, yet we know it's possible (unless std::function uses some compiler built-ins, or otherwise is implemented internally in the compiler rather than being normal C++ code).
Note that I'm using a compiler that doesn't have full C++17 support, so I can't use e. g. auto-deduced return type.
You need to rewrite your base class as follows:
template <typename Ret, typename... Args>
class CInvokableAbstract {
virtual ~CInvokableAbstract() = default;
virtual Ret operator()(Args... args) = 0;
};
This will make your base class dependent on the signature (which it has to be in order to be usable) and provide the actual interface for the invocable object.
Note that this part of code actually has nothing to do with type-erase, it's just plain old dynamic polymorphism. It's the combination of static (CInvokableBasic template) and dynamic (CInvokableAbstract interface) polymorphisms that make type-erasure possible.

How to make constructor accepting std::function also accept method pointers

Say I have
class Foo
{
public:
Foo(std::function<void(std::string)> callback1,
std::function<void(int)> callback2) :
callback1(callback1), callback2(callback2)
{
}
private:
std::function<void(std::string)> callback1;
std::function<void(int)> callback2
}
I can easily construct it in the case I'm using plain functions
void callback1Handler(std::string)
{
// i'm a potato
}
void callback2Handler(int)
{
// i'm a teapot
}
int main()
{
Foo foo(callback1Handler, callback2Handler);
return 0;
}
But if I'm using a class, then things get complicated.
I'd like to be able to do something like the Addendum of this answer does
class Main
{
public:
Main()
{
Foo foo(&Main::callback1Handler, &Main::callback2Handler);
}
void callback1Handler(std::string)
{
// i'm a potato
}
void callback2Handler(int)
{
// i'm a teapot
}
}
But that obviously wouldn't compile. To make it work one would need to use either std::bind or lambdas, or something else.
I want to try to avoid the ugliness of std::bind(&Main::callbackNHandler, this, std::placeholders::_1, ..., std::placeholders::_N), which is mostly the ugliness of having those placeholders explicitly specified.
Using lambdas as [=](std::string str){callbackNHandler(str);} is also ugly, because you have to specify every single variable the callback accepts.
It would be great if I could just use &Main::callback1Handler, just like in the Main class example, or &Main::callback1Handler, this, which is a bit more flexible, since you can specify the instance pointer of Main.
Note that Foo constructor has to remain the same and callback1&callback2 member variables have to also remain the same. However, you may overload Foo constructor, making the overload convert method pointers (or whatever else you will make it to accept) into std::functions and store them in callback1&callback2.
template<class T, class R, class...Args>
std::function<R(Args...)> method( T* t, R(T::*m)(Args...) ){
return [=](Args&&...args)->R{
return (t->*m)(std::forward<Args>(args)...);
};
}
then method( instance, &Main::callback1Handler ) should work, up to typos.
It gets simpler in C++14.
The above does needless type erasure: a helper type instead of a lambda lets you avoid that.
template<class T, class Sig>
struct method_t;
template<class T, class R, class... Args>
struct method_t<T,R(Args...)> {
T* t;
R(T::*m)(Args...);
template<class...Ts>
R operator()(Ts&&...ts)const{
return (t->*m)(std::forward<Ts>(ts)...);
}
};
template<class T, class R, class...Args>
method_t<T, R(Args...)> method( T* t, R(T::*m)(Args...) ){
return {t, m};
}
with the same signature. It can even be stored in a std::function<R(Args...)>. The advantage of the above is that there is no needless overhead if the signature of the std::function does not exactly match, or if you don't use a std::function at all.
The downside is 3x as much code.
In C++14 we can simply do:
template<class T, class R, class...Args>
auto method( T* t, R(T::*m)(Args...) ){
return [=](auto&&...args)->R{
return (t->*m)(decltype(args)(args)...);
};
}
which is as brief as the first one, and as powerful as the second one.
Using lambdas as [=](std::string str){callbackNHandler(str);} is also ugly, because you have to specify every single variable the callback accepts.
C++14 generic lambdas solve that problem:
[this](auto... args){ callback1Handler(args...); }
For C++11 you could write a simple utility that can be used like so:
Foo foo(simple_bind(&Main::callback1Handler, this),
simple_bind(&Main::callback2Handler, this));
That would be defined as a function template like this:
template<typename T, typename F>
SimpleBinder<T, F>
simple_bind(F T::* memfn, T* that)
{ return { that, memfn }; }
Where the type SimpleBinder<T, F> is just:
template<typename T, typename F>
struct SimpleBinder
{
T* m_this;
F T::* m_memfn;
template<typename... Args>
void operator()(Args&&... args)
{ (m_this->*m_memfn)(std::forward<Args>(args)...); }
};
This isn't a fully generic utility (for example, it doesn't do anything with the return type of the member function, always returning void, but that is OK for your requirements, where both the std::function objects return void anyway), but it solves the problem of associating an arbitrary member function with a this pointer, and then calling it with some set of arguments.
Although the SimpleBind object appears to accept any arguments, in fact you'll get a nasty compiler error if you try to call it with arguments that aren't compatible with the member function it binds. Again, that's not a problem, because the std::function objects you store it in will ensure that only the right type of arguments are ever passed to it.

How to create a variadic template function with `std::function` as a function parameter?

How can I create a variadic template function with std::function as a function parameter that accepts a variadic number of arguments? I tried to reduce the problem to a MWE:
#include <functional>
template <class T> void run(std::function<void(T *)> fun, T *obj) { fun(obj); }
template <class T, class... Args>
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args... args) {
fun(obj, args...);
}
struct Foo {
void bar() {}
};
int main() {
Foo foo;
std::function<void(Foo *)> fun = &Foo::bar;
run(fun, &foo); // works
run<Foo>(&Foo::bar, &foo); // works
run_variadic(fun, &foo); // works
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
}
It seems like the mere presence of the variadic template parameter in run_variadic makes it impossible to directly call it with a member function pointer. clang's error message is as follows:
main.cpp:21:3: error: no matching function for call to 'run_variadic'
run_variadic<Foo>(&Foo::bar, &foo); // does not compile
^~~~~~~~~~~~~~~~~
main.cpp:6:6: note: candidate template ignored: could not match 'function<void (Foo *, type-parameter-0-1...)>' against 'void (Foo::*)()'
void run_variadic(std::function<void(T *, Args...)> fun, T *obj, Args&&... args) {
^
1 error generated.
Any suggestions on how I can fix run_variadic so that I do not have to go through the extra std::function object?
Background
I have a class hierarchy as
template <class T> class Abstract { ... };
class UnrelatedStuff { ... };
class Derived : public Abstract<UnrelatedStuff> { ... };
There are multiple Derived classes that all have to implement one or more methods to loop over a range of elements. The loop looks something like
#pragma omp parallel for
for (ZFSId i = begin; i != end; ++i) {
callMemFun(i, and, other, args);
}
All loops should be OpenMP-accelerated. I want the accelerator stuff factored out and not repeated in each method of Derived that uses a loop, so that I only have to change one place if e.g. OpenMP would switch to OpenACC.
Thus I am looking for a way to put the loop (and its decoration) in its own function. Moving it to the Abstract base class is not an option either, since the loops are performance-critical and I cannot have an abstract function call in each loop iteration.
You are almost always certainly better off abstracting away the function object:
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
This allows you to do the right thing at call site:
// function object is a lambda that binds to a member function:
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args...*/);
I prefer a lambda to std::function or std::bind but you can also use those if they are already available:
run(std::function<void(Foo *)>{&Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
I provide a full example program below.
You have now edited the question with new information regarding what you are trying to do.
I'm pretty sure that you don't want to do this, since the OpenMP/OpenACC pragmas like parallel for usually require extra annotations for delivering reasonable performance, and they depend on what you are exactly trying to do at call site.
Still, if you really really want to go this route you can write your own for_each algorithm and dispatch according to an ExecutionAgent (see N3874 and N3731). If OpenMP, TBB, OpenACC parallel task are too slow, you can also easily provide overloads based on e.g. an ExecutionPolicy like this:
template<class RandomAccessRange, class Functor,
class ExecutionPolicy = execution::serial_t>
void for_each(RandomAccessRange&& r, Functor&& f,
ExecutionPolicy&& ex = ExecutionPolicy{}) {
detail::for_each_(std::forward<RandomAccessRange>(r),
std::forward<Functor>(f),
std::forward<ExecutionPolicy>(ex));
}
And then you can implement overloads of for_each_ for each execution policy, e.g.:
namespace detail {
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::serial_t) {
boost::for_each(std::forward<RandomAccessRange>(r), std::forward<Functor>(f));
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openmp_t) {
#pragma omp parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::openacc_t) {
#pragma acc parallel for
for (auto&& v : r) { f(v); }
}
template<class RandomAccessRange, class Functor>
void for_each(RandomAccessRange&& r, Functor&& f, execution::tbb_t) {
tbb::parallel_for_each(std::begin(std::forward<RandomAccessRange>(r)),
std::end(std::forward<RandomAccessRange>(r)),
std::forward<Functor>(f));
}
} // namespace detail
Note that the ExecutionPolicy is just a tag, i.e.:
namespace execution {
struct serial_t {}; static const constexpr serial_t serial{};
struct openmp_t {}; static const constexpr openmp_t openmp{};
struct openacc_t {}; static const constexpr openacc_t openacc{};
struct tbb_t {}; static const constexpr tbb_t tbb{};
} // namespace execution
This will at least give you an efficient TBB backend even tho the OpenMP/OpenACC performance will be mediocre at best. You can take a look at the parallel implementation of libstdc++ where they use OpenMP. Their for_each algorithm is over 1000 lines of code and uses work-stealing.
Full example program:
#include <functional>
template <class Functor, class... Args>
void run(Functor&& f, Args&&... args) {
f(std::forward<Args>(args)...);
}
struct Foo { void bar() {} };
int main() {
Foo foo;
run([&](auto... args) { foo.bar(args...); } /*, bar takes no args*/);
run(std::function<void(Foo *)>{ &Foo::bar}, &foo);
run(std::bind(&Foo::bar, &foo));
run(std::mem_fn(&Foo::bar), foo);
}
To answer your comment on the previous answer, that answer can be adapted to support pointers to member functions in the way that you've asked for. The previous answer already works for all callable objects, but not directly with a pointer to member function because those are not callable with the usual f(args) syntax. The following version uses tag dispatch to distinguish between pointers to member functions and traditional callable objects, applying the call syntax appropriate to each case.
template <class Functor, class... Args>
void run_helper(std::false_type, Functor f, Args&&... args)
{
f(std::forward<Args>(args)...);
}
template <class Functor, class Arg0, class... Args>
void run_helper(std::true_type, Functor f, Arg0&& arg0, Args&&... args)
{
(std::forward<Arg0>(arg0).*f)(std::forward<Args>(args)...);
}
template <class Functor, class... Args>
void run(Functor f, Args&&... args)
{
run_helper(typename std::is_member_pointer<Functor>::type(),
f, std::forward<Args>(args)...);
}
This can be used in all the same ways as the previous answer could, but also supports directly passing in a pointer to member function:
run(&Foo::bar, foo);
It even works with overloaded member functions and member functions which are templates, if you explicitly instantiate the run template to bind to a particular overloaded function or function template instantiation.
Live example: http://ideone.com/vsBS4H