std::enable_if and std::shared_ptr - c++

Goal: Having function dispatching working as intended. The minimal example code should speak for itself. I want to support tasks: Named task, that are implemented in their own class, and simpler task, specified using lambda. Ideally, anything that can be converted to std::function<void (void)> should work.
#include <iostream>
#include <memory>
#include <functional>
// A Base class for my tasks
class BaseTask
{
public:
virtual void blah() = 0;
};
// An important enough tasks that it gets to have its
// own class.
class NamedTask : public BaseTask
{
public:
virtual void blah()
{
std::cout << "Hey !" << std::endl;
}
};
// A wrapper around simpler tasks. (lambda)
class GenericTask : public BaseTask
{
public:
GenericTask(const std::function<void (void)> fct) :
fct_(fct) {}
virtual void blah() override
{
fct_();
}
private:
std::function<void (void)> fct_;
};
void enqueue(std::shared_ptr<BaseTask> t)
{
// store in queue.
// We'll just call it here for the sake of the example
t->blah();
}
template<typename Callable>
//typename std::enable_if<!std::is_base_of<BaseTask, Callable>::value>::type
//typename std::enable_if<!std::is_base_of<std::shared_ptr<BaseTask>, Callable>::value>::type
void enqueue(const Callable &c)
{
auto t = std::make_shared<GenericTask>(c);
t->blah();
}
int main()
{
auto named = std::make_shared<NamedTask>();
enqueue(named); // doesn't compile: tries to call the templated enqueue.
enqueue([] () -> bool { std::cout << "Lamda" << std::endl; });
}
Problem: I don't manage to write a proper enable_if template. The commented lines in the example is what I tried.
The first one doesn't work because Callable is of type std::shared_ptr<NamedTask>, which is not a child of BaseTask.
The second one fails too, presumably because std::shared_ptr<NamedTask> does not derive from std::shared_ptr<BaseTask>.

You have two cases: your callable is convertible to shared_ptr<BaseTask>, or not. Checking the base is incorrect as shared_ptr<NamedTask> is not related by class hierarchy to shared_ptr<BaseTask>, but you can construct a shared_ptr<BaseTask> from it.
That is:
// is convertible to shared_ptr<BaseTask>
void enqueue(std::shared_ptr<BaseTask> t);
// is NOT convertible to shared_ptr<BaseTask>
template<typename Callable>
typename std::enable_if<
!std::is_convertible<Callable, std::shared_ptr<BaseTask>>::value
>::type
enqueue(const Callable &c);
Alternatively, you can think of the two cases as constructible/not constructible:
template<typename Callable>
typename std::enable_if<
!std::is_constructible<std::shared_ptr<BaseTask>, Callable>::value
>::type
enqueue(const Callable &c);
Third alternative is to condition the function template enqueue on anything that is callable with zero arguments:
template<typename Callable>
auto enqueue(const Callable &c) -> decltype(c(), void())

Related

How to initiate std::unique_ptr in the constructor with std::make_unique() [duplicate]

I have a class with a unique_ptr member.
class Foo {
private:
std::unique_ptr<Bar> bar;
...
};
The Bar is a third party class that has a create() function and a destroy() function.
If I wanted to use a std::unique_ptr with it in a stand alone function I could do:
void foo() {
std::unique_ptr<Bar, void(*)(Bar*)> bar(create(), [](Bar* b){ destroy(b); });
...
}
Is there a way to do this with std::unique_ptr as a member of a class?
Assuming that create and destroy are free functions (which seems to be the case from the OP's code snippet) with the following signatures:
Bar* create();
void destroy(Bar*);
You can write your class Foo like this
class Foo {
std::unique_ptr<Bar, void(*)(Bar*)> ptr_;
// ...
public:
Foo() : ptr_(create(), destroy) { /* ... */ }
// ...
};
Notice that you don't need to write any lambda or custom deleter here because destroy is already a deleter.
It's possible to do this cleanly using a lambda in C++11 (tested in G++ 4.8.2).
Given this reusable typedef:
template<typename T>
using deleted_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
You can write:
deleted_unique_ptr<Foo> foo(new Foo(), [](Foo* f) { customdeleter(f); });
For example, with a FILE*:
deleted_unique_ptr<FILE> file(
fopen("file.txt", "r"),
[](FILE* f) { fclose(f); });
With this you get the benefits of exception-safe cleanup using RAII, without needing try/catch noise.
You just need to create a deleter class:
struct BarDeleter {
void operator()(Bar* b) { destroy(b); }
};
and provide it as the template argument of unique_ptr. You'll still have to initialize the unique_ptr in your constructors:
class Foo {
public:
Foo() : bar(create()), ... { ... }
private:
std::unique_ptr<Bar, BarDeleter> bar;
...
};
As far as I know, all the popular c++ libraries implement this correctly; since BarDeleter doesn't actually have any state, it does not need to occupy any space in the unique_ptr.
Unless you need to be able to change the deleter at runtime, I would strongly recommend using a custom deleter type. For example, if use a function pointer for your deleter, sizeof(unique_ptr<T, fptr>) == 2 * sizeof(T*). In other words, half of the bytes of the unique_ptr object are wasted.
Writing a custom deleter to wrap every function is a bother, though. Thankfully, we can write a type templated on the function:
Since C++17:
template <auto fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, auto fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<fn>>;
// usage:
my_unique_ptr<Bar, destroy> p{create()};
Prior to C++17:
template <typename D, D fn>
struct deleter_from_fn {
template <typename T>
constexpr void operator()(T* arg) const {
fn(arg);
}
};
template <typename T, typename D, D fn>
using my_unique_ptr = std::unique_ptr<T, deleter_from_fn<D, fn>>;
// usage:
my_unique_ptr<Bar, decltype(&destroy), destroy> p{create()};
You know, using a custom deleter isn't the best way to go, as you will have to mention it all over your code.
Instead, as you are allowed to add specializations to namespace-level classes in ::std as long as custom types are involved and you respect the semantics, do that:
Specialize std::default_delete:
template <>
struct ::std::default_delete<Bar> {
default_delete() = default;
template <class U>
constexpr default_delete(default_delete<U>) noexcept {}
void operator()(Bar* p) const noexcept { destroy(p); }
};
And maybe also do std::make_unique():
template <>
inline ::std::unique_ptr<Bar> ::std::make_unique<Bar>() {
auto p = create();
if (!p)
throw std::runtime_error("Could not `create()` a new `Bar`.");
return { p };
}
You can simply use std::bind with a your destroy function.
std::unique_ptr<Bar, std::function<void(Bar*)>> bar(create(), std::bind(&destroy,
std::placeholders::_1));
But of course you can also use a lambda.
std::unique_ptr<Bar, std::function<void(Bar*)>> ptr(create(), [](Bar* b){ destroy(b);});
#include "fmt/core.h"
#include <memory>
class example {};
void delete_example(example *)
{
fmt::print("delete_example\n");
}
using example_handle = std::unique_ptr<example, decltype([] (example * p)
{
delete_example(p);
})>;
int main()
{
example_handle handle(new example);
}
Just my two cents, using C++20.
https://godbolt.org/z/Pe3PT49h4
With a lambda you can get the same size as a plain std::unique_ptr. Compare the sizes:
plain: 8
lambda: 8
fpointer: 16
std::function: 40
Which is the output of the following. (I declared the lambda outside the scope of the class. Not sure if you can scope it inside the class.)
#include <iostream>
#include <memory>
#include <functional>
struct Bar {};
void destroy(Bar* b) {}
Bar* create() { return 0; }
auto lambda_destroyer = [](Bar* b) {destroy(b);};
class Foo {
std::unique_ptr<Bar, decltype(lambda_destroyer)> ptr_;
public:
Foo() : ptr_(create(), lambda_destroyer) { /* ... */ }
};
int main()
{
std::cout << "plain: " << sizeof (std::unique_ptr<Bar>) << std::endl
<< "lambda: " << sizeof (std::unique_ptr<Bar, decltype(lambda_destroyer)>) << std::endl
<< "fpointer: " << sizeof (std::unique_ptr<Bar, void(*)(Bar*)>) << std::endl
<< "std::function: " << sizeof (std::unique_ptr<Bar, std::function<void(Bar*)>>) << std::endl;
}
I'm fairly convinced that this is the best current way to do it:
#include <memory>
#include <stdio.h>
template <typename T, auto fn>
struct Deleter
{
void operator()(T *ptr)
{
fn(ptr);
}
};
template <typename T, auto fn>
using handle = std::unique_ptr<T, Deleter<T, fn>>;
using file = handle<FILE, fclose>;
int main()
{
file f{fopen("a.txt", "w")};
return 0;
}
Because you've specified a Functor as the deleter in the unique_ptr's template arguments, you don't need to set a deleter when calling its constructor.
The Deleter functor uses "template auto" to take a deletion function (in this example: fclose) as a template argument, so this needs C++17.
Expanding it to support other types is just one extra "using" line per type.
Simple is also:
class Foo {};
class Bar
{
public:
Bar()
{
// actual initialisation at some point
}
private:
std::unique_ptr<Foo, void(*)(Foo*)> foo = {{}, {}}; // or = {nullptr, {}}
};
Sure, you can also create some helper function to do the job to not have the initial state at any time.
In fact, in your specific scenario, the cleanest way is to actually put your Bar (not mine, sorry for the confusion) into a simple wrapper class, which makes reuse easier.

How to use std::bind with the standard library and save the return type?

I'm working on a class that schedules functions by binding them in a queue like this:
std::queue <void()> q;
template<typename R,typename... ArgsT>
void
schedule(R& fn, ArgsT&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
As you see I made the type in the queue void() to make it hold any type of function objects but now I can't get the return when I execute it. What should I do to solve this?
Note: I don't want to use an external library like boost and I don't know what kind of function the user will pass it.
Note: I don't want to use an external library like boost and I don't
know what's the kind of function the user will pass it.
What I usually do in this case is I use a base class (from Command pattern) in my queue, and then have two implementations, the one wrapping the bind, and the other (also wrapping the bind) exposing a function that allows getting the return value.
Here is an example of the returning specialization (at last):
#include <iostream>
#include <functional>
#include <memory>
struct ACmd
{
virtual void exec() = 0;
virtual ~ACmd(){}
};
template <class F>
struct Cmd;
template <class R, class ... Args>
struct Cmd<R(Args...)> : ACmd
{
R result_;
std::function<R()> func_;
template <class F>
Cmd(F&& func, Args&&... args): result_(), func_()
{
auto f = std::bind(std::forward<F>(func), std::forward<Args>(args)...);
func_ = [f](){
return f();
};
}
virtual void exec(){
result_ = func_();
}
const R& getResult() const {return result_;}
};
// Make function for convenience, could return by value or ptr -
// - your choice
template <class R, class F, class ...Args>
Cmd<R(Args...)>* cmd(F&& func, Args&&... args)
{
return new Cmd<R(Args...)>(func, std::forward<Args>(args)...);
}
//... And overload for void...
int foo(int arg) {
return arg;
}
int main() {
auto x = cmd<int>(foo, 10);
x->exec();
std::cout << x->getResult() << std::endl;
return 0;
}
The result of the execution of each element in the queue, it is void, you have already defined it as such. If the functions passed in are required to return a value, then you would need to limit the type(s) returned to a fixed type, use utilities such as std::any, std::variant or some covariant types (possible with a std::unique_ptr or std::shared_ptr).
The simplest is to fix the return type (at compile time);
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
See the sample below.
The queue declaration needs to be a queue of objects, such as std::function objects. The return value from a bind can be assigned to a function and then used as expected.
std::function is a polymorphic function wrapper, it implements type erasure patterns akin to any, but is specifically designed for functions and other callable objects.
By way of example;
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(std::forward<R>(fn), std::forward<ArgsT>(args)...) );
};
int main()
{
schedule([](int a) { std::cout << "function called" << std::endl; return a; }, 42);
std::cout << q.front()() << std::endl;
}

Cannot call generic std::function member from template class

When compiling the following code:
#include <functional>
template <typename functionSignature>
class Class
{
std::function<functionSignature> func;
public:
Class(const std::function<functionSignature>& arg) : func(arg) {}
void callFunc() { func(); }
};
void f(const int i) {}
int main()
{
Class<void(const int)> a(std::bind(f, 10));
a.callFunc();
return 0;
}
The VS 2015 compiler generates the following error message at the sixth line:
error C2064: term does not evaluate to a function taking 0 arguments.
Now, I believe this is because the compiler thinks functionSignature is not, well, a function signature; the same error happens when I instantiate and try to call operator() on an std::function<int> instead of std::function<int()>, for instance.
How can I guarantee that the template argument will always be a function signature, so that I can call operator() on the std::function?
I suspect you want something like that:
template <typename F>
class Class;
template<typename R, typename... P>
class Class<R(P...)> {
public:
std::function<R(P...)> func;
void callFunc(P... p) { func(p...); }
};
By using partial specialization that way you can easily define the type you want.
As an example, you can use it as:
Class<int(double)> c;
Of course, I noticed that you have no constructors for your class, so to invoke func is not a good idea, but it's quite easy to define it and pass a proper function as an argument.
It follows a complete and working example where I've used the operator() to invoke the function:
#include <functional>
template <typename F>
class Class;
template<typename R, typename... P>
class Class<R(P...)> {
public:
Class(std::function<R(P...)> f): func{f} { }
void operator()(P... p) { func(p...); }
private:
std::function<R(P...)> func;
};
void fn() { }
int main() {
std::function<void()> f = fn;
Class<void()> c{f};
c();
}
Your error is here:
Class<void(const int)> a(std::bind(f, 10));
The function Class::callFunc() invokes func() -- i.e., no arguments. The result of std::bind(f, 10) is also a function that takes no arguments, which is consistent with the template argument to the class template. Using Class<void(const int)> is inconsistent with both the usage in the class template and the initialization.
The solution is easy: Change the errant line to
Class<void()> a(std::bind(f, 10));
Is this what you are trying to do?
http://ideone.com/fork/IZ0Z1A
If functionSignature is NOT a function, std::function will throw errors when you create Class but you could add a constructor and throw there a static_assert(std::is_function<functionSignature>::value == true," ");if you want I guess.
#include <functional>
#include <iostream>
template <typename functionSignature>
class Class
{
public:
std::function<functionSignature> func;
void callFunc() { func(); }
};
void f()
{
std::cout << "hello" << std::endl;
}
int main()
{
Class<decltype(f)> t {f};
t.callFunc();
return 0;
}

Too many copies when binding variadic template arguments

I'm creating a job queue. The job will be created in thread A, then the job will be sent to thread B and thread B will do the job. After the job has been done, the job will be sent back to thread A.
#include <functional>
#include <iostream>
#include <memory>
using namespace std;
template<typename T, typename... Args>
class Job
{
public:
Job(std::weak_ptr<T> &&wp, std::function<void(const Args&...)> &&cb)
: _cb(std::move(cb)),
_cbWithArgs(),
_owner(std::move(wp)) {}
public:
template<typename... RfTs>
void bind(RfTs&&... args)
{
// bind will copy args for three times.
_cbWithArgs = std::bind(_cb, std::forward<RfTs>(args)...);
}
void fire()
{
auto sp = _owner.lock();
if (sp)
{
_cbWithArgs();
}
}
private:
std::function<void(const Args& ...)> _cb;
std::function<void()> _cbWithArgs;
std::weak_ptr<T> _owner;
};
struct Args
{
Args() = default;
Args(const Args &args)
{
cout << "Copied" << endl;
}
};
struct Foo
{
void show(const Args &)
{
cout << "Foo" << endl;
}
};
int main()
{
using namespace std::placeholders;
shared_ptr<Foo> sf (new Foo());
Args args;
// Let's say here thread A created the job.
Job<Foo, Args> job(sf, std::bind(&Foo::show, sf.get(), _1));
// Here thread B has finished the job and bind the result to the
// job.
job.bind(args);
// Here, thread A will check the result.
job.fire();
}
The above codes compiles and works. But it gives the following results (g++ 4.8.4 & clang have the same results):
Copied
Copied
Copied
Foo
There are three copies! Not acceptable, I don't know where I did wrong. Why three copies? I googled and find a method from here: https://stackoverflow.com/a/16868401, it only copys params for one time. But it has to initialize the bind function in constructor.
Thanks, Piotr Skotnicki. Unfortunately, I don't have a C++14 compiler. So, let's make the Args movable:
struct Args
{
Args() = default;
Args(const Args &args)
{
cout << "Copied" << endl;
}
Args(Args &&) = default;
Args& operator=(Args &&) = default;
};
Now, it copys just one time :)
Finally, I adopted the codes from this thread https://stackoverflow.com/a/16868151/5459549. The template gen_seq is true ART, I must say.
The first copy is made by the std::bind itself:
std::bind(_cb, std::forward<RfTs>(args)...)
as it needs to store decayed-copies of its arguments.
The other two copies are made by the assignment to _cbWithArgs which is of type std::function (ยง 20.8.11.2.1 [func.wrap.func.con]):
template<class F> function& operator=(F&& f);
18 Effects: function(std::forward<F>(f)).swap(*this);
where:
template<class F> function(F f);
9 [...] *this targets a copy of f initialized with std::move(f).
That is, one copy for the parameter of a constructor, and another one to store argument f.
Since Args is a non-movable type, an attempt to move from a result of a call to std::bind falls back to a copy.
It doesn't seem reasonable in your code to store the results of job execution in a std::function. Instead, you can store those values in a tuple:
template <typename T, typename... Args>
class Job
{
public:
Job(std::weak_ptr<T> wp, std::function<void(const Args&...)> &&cb)
: _cb(std::move(cb)),
_owner(wp) {}
public:
template<typename... RfTs>
void bind(RfTs&&... args)
{
_args = std::forward_as_tuple(std::forward<RfTs>(args)...);
}
void fire()
{
auto sp = _owner.lock();
if (sp)
{
apply(std::index_sequence_for<Args...>{});
}
}
private:
template <std::size_t... Is>
void apply(std::index_sequence<Is...>)
{
_cb(std::get<Is>(_args)...);
}
std::function<void(const Args&...)> _cb;
std::weak_ptr<T> _owner;
std::tuple<Args...> _args;
};
DEMO

Abstraction over single c++ object and std::pair of objects using templates

Assume the following template construction:
enum class ENUM {SINGLE, PAIR};
// General data type
template<ENUM T, class U>class Data;
// Partially specialized for single objects
template<class U>Data<ENUM::SINGLE, U> : public U {
// Forward Constructors, ...
};
// Partially specialized for pairs of objects
template<class U>Data<ENUM::PAIR, U> : public std::pair<U,U> {
// Forward Constructors, ...
};
In my code I want to be able to write something like
template<ENUM T>someMethod(Data<T, SomeClass> data) {
for_single_or_pair {
/*
* Use data as if it would be of type SomeClass
*/
}
}
which should do the same as the combination of the following methods:
template<>someMethod(Data<ENUM::SINGLE, SomeClass> data) {
data.doStuff();
}
template<>incrementData(Data<ENUM::PAIR, SomeClass> data) {
data.first.doStuff();
data.second.doStuff();
}
I.e. I want to be able to use a pair of objects (of the same type) as if it would be a single object. Of course I could reimplement the methods of a type T for Data<ENUM::PAIR, T> (see the answer of dau_sama) which for the given example would look like:
template<>Data<ENUM::PAIR, SomeClass> : public std::pair<SomeClass, SomeClass> {
doStuff() {
this->first.doStuff();
this->second.doStuff();
}
};
But I would have to do this for many methods and operators and many different types, although the methods and operators would all look like this example.
The syntax of the solution may be very different from what I wrote above, this is just to demonstrate what I want to achieve. I would prefer a solution without macros, but could also live with that.
Can such an abstraction be realized in C++11?
The reasons I want to do this are
I do not have to specialize templated methods that shall work for ENUM::Single and ENUM::PAIR when all differences between the specializations would math the pattern above (avoid a lot of code duplication).
The same pattern is occuring very often in my code and I could avoid implementing workarounds in many places, which would be almost identical in each case.
You could try to create a template method applyMethod. Here is a complete example. I used an Executor class containing only one static method because I could not find a better way to process methods taking any types of parameters
#include <iostream>
#include <string>
enum ENUM {SINGLE, PAIR};
// General data type
template<ENUM T, class U>class Data {
};
// Partially specialized for single objects
template<class U>
class UData : public Data<ENUM::SINGLE, U>, public U {
// Forward Constructors, ...
public:
UData(const U& u): U(u) {};
};
// Partially specialized for pairs of objects
template<class U>
class PData : public Data<ENUM::PAIR, U>, public std::pair<U,U> {
// Forward Constructors, ...
public:
PData(const U& u1, const U& u2): std::pair<U, U>(u1, u2) {};
};
template <class U, typename... P>
class Executor {
Executor() = delete;
public:
template<void (U::*M)(P... params)>
static void applyMethod(Data<ENUM::SINGLE, U> &data, P ...params) {
UData<U>& ud= reinterpret_cast<UData<U>& >(data);
U& u = static_cast<U&>(ud);
(u.*M)(params...);
}
template<void (U::*M)(P... params)>
static void applyMethod(Data<ENUM::PAIR, U> &data, P ...params) {
PData<U>& pd = reinterpret_cast<PData<U>& >(data);
(pd.first.*M)(params...);
(pd.second.*M)(params...);
}
};
class X {
std::string name;
public:
X(const std::string& name): name(name) { };
void doStuff(void) {
std::cout << "DoStuff : " << name << std::endl;
}
void doStuff(int i) {
std::cout << "DoStuff : " << name << " - " << i << std::endl;
}
};
int main() {
X x1("x1");
X x2("x2");
X x3("x3");
UData<X> data1(x1);
PData<X> data2(x2, x3);
Executor<X>::applyMethod<&X::doStuff>(data1);
Executor<X, int>::applyMethod<&X::doStuff>(data2, 12);
return 0;
}
You could add a common method to your classes
template<class U>
Data<ENUM::SINGLE, U> : public U {
// Forward Constructors, ...
void handle() {
//do some specific handling for this type
return;
}
};
Now someMethod will just call the right "handle" and it'll automatically switch between the two
template<typename T>
someMethod(T& data) {
data.handle();
}
//If you want to bind your function to some other name, you could
//create a functor that calls someMethod with the arguments passed in _1
//I haven't tested it, there might be some syntax problems with the way you pass in the function name
auto someOtherMethod = std::bind (someMethod, _1);
If your type doesn't implement a handle method, you'll have a nasty compilation error. If you want to provide a default implementation and avoid a compilation error, there is a common pattern called SFINAE (Substitution failure is not an error) that does exactly that.
Here's an alternative to the solution to that from Serge Ballesta, using lambdas.
#include <functional>
template<ENUM T, class U>void for_single_or_pair(
Data<T, U>& data,
std::function<void(U&)> function);
template<class U>void for_single_or_pair(
Data<ENUM::SINGLE, U>& data,
std::function<void(U&)> function) {
function(data);
}
template<class U>void for_single_or_pair(
Data<ENUM::PAIR, U>& data,
std::function<void(U&)> function) {
function(data.first);
function(data.second);
}
Usage:
template<ENUM T>someMethod(Data<T, SomeClass> data) {
for_single_or_pair(data,[](SomeClass& someObject) {
// Play around with someObject in any way
});
}
In this way additionally to use member methods of SomeClass, the data can be used in any other way.
I would be happy about comments to this solution (and if it could be generalized to use more than one Data inside the for_single_or_pair method).