I am working in a memory constrained embedded environment where malloc/free new/delete are not advisable, and I'm trying to use the std::function pattern to register callbacks. I do not have access to any of the STL methods in my target code so I'm in the unfortunate situation of having to replicate some of the STL functionality myself. Function pointers are not an option for me due to the necessity for callers to have captures.
For instance, I wish to declare a class Mailbox where an onChange event can be registered
class Mailbox {
std::function<void(int,int)> onChange;
};
That way, callers can register a lambda onChange handler that could capture this or other variables that matter for handling the event.
Since this is part of an API, I want to give the users of Mailbox maximim flexibility to either provide a function pointer, a lambda or a functor.
I have managed to find a great implementation of a std::function that appears to be exceptionally low-overhead and has exactly what I need except that it involves dynamic memory.
If you look at the following code, dynamic memory is used in exactly one place, and it appears fully scoped to the object being templated, suggesting to me that its size ought to be known at compile-time.
Can anyone help me understand how to refactor this implementation so that it is fully static and removes the use of new/malloc? I'm having trouble understanding why the size of CallableT wouldn't be calculable at compile-time.
Code below (not for the faint of heart). Note, it uses make_unique / unique_ptr but those can easily be substituted with new and * and I have tested that use case successfully.
#include <iostream>
#include <memory>
#include <cassert>
using namespace std;
template <typename T>
class naive_function;
template <typename ReturnValue, typename... Args>
class naive_function<ReturnValue(Args...)> {
public:
template <typename T>
naive_function& operator=(T t) {
callable_ = std::make_unique<CallableT<T>>(t);
return *this;
}
ReturnValue operator()(Args... args) const {
assert(callable_);
return callable_->Invoke(args...);
}
private:
class ICallable {
public:
virtual ~ICallable() = default;
virtual ReturnValue Invoke(Args...) = 0;
};
template <typename T>
class CallableT : public ICallable {
public:
CallableT(const T& t)
: t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return t_(args...);
}
private:
T t_;
};
std::unique_ptr<ICallable> callable_;
};
void func() {
cout << "func" << endl;
}
struct functor {
void operator()() {
cout << "functor" << endl;
}
};
int main() {
naive_function<void()> f;
f = func;
f();
f = functor();
f();
f = []() { cout << "lambda" << endl; };
f();
}
Edit: added clarification on STL
The name for what you're looking for is "in-place function". At least one very good implementation exists today:
sg14::inplace_function<R(A...), Size, Align>
There is also tj::inplace_any<Size, Align>, if you need/want the semantics of any.
Let me preface this answer by saying that storing a general callable faces an interesting choice in terms of memory management. Yes, we can deduce the size of any callable at compile time but we can not store any callable into the same object without memory management. That's because our own object needs to have size independently of the callables its supposed to store but those can be arbitrarily big.
To put this reasoning into one sentence: The layout of our class (and its interface) needs to be compiled without knowledge about all of the callers.
This leaves us with essentially 3 choices
We embrace memory management. We dynamically copy the callable and properly manage that memory through means of unique pointer (std or boost), or through custom calls to new and delete. This is what the original code you found does and is also done by std::function.
We only allow certain callables. We create some custom storage inside our object to hold some forms of callables. This storage has a pre-determined size and we reject any callable given that can not adhere to this requirement (e.g. by a static_assert). Note that this does not necessarily restrict the set of possible callers. Instead, any user of the interface could set up a proxy-class holding merely a pointer but forwarding the call operator. We could even offer such a proxy class ourselves as part of the library. But this does nothing more than shifting the point of allocation from inside the function implementation to outside. It's still worth a try, and #radosław-cybulski comes closest to this in his answer.
We don't do memory management. We could design our interface in a way that it deliberately refuses to take ownership of the callable given to it. This way, we don't need to to memory management and this part is completely up to our caller. This is what I will give code for below. It is not a drop-in replacement for std::function but the only way I see to have a generic, allocation-free, copiable type for the purpose you inteded it.
And here is the code for possibility 3, completely without allocation and fully self-contained (does not need any library import)
template<typename>
class FunctionReference;
namespace detail {
template<typename T>
static T& forward(T& t) { return t; }
template<typename T>
static T&& forward(T&& t) { return static_cast<T&&>(t); }
template<typename C, typename R, typename... Args>
constexpr auto get_call(R (C::* o)(Args...)) // We take the argument for sfinae
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<C*>(t)->operator())(forward<Args>(args)...); };
}
template<typename C, typename R, typename... Args>
constexpr auto get_call(R (C::* o)(Args...) const) // We take the argument for sfinae
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<const C*>(t)->operator())(forward<Args>(args)...); };
}
template<typename R, typename... Args>
constexpr auto expand_call(R (*)(Args...))
-> typename FunctionReference<R(Args...)>::ptr_t {
return [](void* t, Args... args) { return (static_cast<R (*)(Args...)>(t))(forward<Args>(args)...); };
}
}
template<typename R, typename... Args>
class FunctionReference<R(Args...)> {
public:
using signature_t = R(Args...);
using ptr_t = R(*)(void*, Args...);
private:
void* self;
ptr_t function;
public:
template<typename C>
FunctionReference(C* c) : // Pointer to embrace that we do not manage this object
self(c),
function(detail::get_call(&C::operator()))
{ }
using rawfn_ptr_t = R (*)(Args...);
FunctionReference(rawfn_ptr_t fnptr) :
self(fnptr),
function(detail::expand_call(fnptr))
{ }
R operator()(Args... args) {
return function(self, detail::forward<Args>(args)...);
}
};
For seeing how this then works in action, go to https://godbolt.org/g/6mKoca
Try this:
template <class A> class naive_function;
template <typename ReturnValue, typename... Args>
class naive_function<ReturnValue(Args...)> {
public:
naive_function() { }
template <typename T>
naive_function(T t) : set_(true) {
assert(sizeof(CallableT<T>) <= sizeof(callable_));
new (_get()) CallableT<T>(t);
}
template <typename T>
naive_function(T *ptr, ReturnValue(T::*t)(Args...)) : set_(true) {
assert(sizeof(CallableT<T>) <= sizeof(callable_));
new (_get()) CallableT<T>(ptr, t);
}
naive_function(const naive_function &c) : set_(c.set_) {
if (c.set_) c._get()->Copy(&callable_);
}
~naive_function() {
if (set_) _get()->~ICallable();
}
naive_function &operator = (const naive_function &c) {
if (this != &c) {
if (set_) _get()->~ICallable();
if (c.set_) {
set_ = true;
c._get()->Copy(&callable_);
}
else
set_ = false;
}
return *this;
}
ReturnValue operator()(Args... args) const {
return _get()->Invoke(args...);
}
ReturnValue operator()(Args... args) {
return _get()->Invoke(args...);
}
private:
class ICallable {
public:
virtual ~ICallable() = default;
virtual ReturnValue Invoke(Args...) = 0;
virtual void Copy(void *dst) const = 0;
};
ICallable *_get() {
return ((ICallable*)&callable_);
}
const ICallable *_get() const { return ((const ICallable*)&callable_); }
template <typename T>
class CallableT : public ICallable {
public:
CallableT(const T& t)
: t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return t_(std::forward<ARGS>(args)...);
}
void Copy(void *dst) const override {
new (dst) CallableT(*this);
}
private:
T t_;
};
template <typename T>
class CallableT<ReturnValue(T::*)(Args...)> : public ICallable {
public:
CallableT(T *ptr, ReturnValue(T::*)(Args...))
: ptr_(ptr), t_(t) {
}
~CallableT() override = default;
ReturnValue Invoke(Args... args) override {
return (ptr_->*t_)(std::forward<ARGS>(args)...);
}
void Copy(void *dst) const override {
new (dst) CallableT(*this);
}
private:
T *ptr_;
ReturnValue(T::*t_)(Args...);
};
static constexpr size_t size() {
auto f = []()->void {};
return std::max(
sizeof(CallableT<void(*)()>),
std::max(
sizeof(CallableT<decltype(f)>),
sizeof(CallableT<void (CallableT<void(*)()>::*)()>)
)
);
};
typedef unsigned char callable_array[size()];
typename std::aligned_union<0, callable_array, CallableT<void(*)()>, CallableT<void (CallableT<void(*)()>::*)()>>::type callable_;
bool set_ = false;
};
Keep in mind, that sort of tricks tend to be slightly fragile.
In this case to avoid memory allocation i used unsigned char[] array of assumed max size - max of CallableT with pointer to function, pointer to member function and lambda object. Types of pointer to function and member function dont matter, as standard guarantees, that for all types those pointers will have the same size. Lambda should be pointer to object, but if for some reason isnt and it's size will change depending on lambda types, then you're out of luck.
First callable_ is initialized with placement new and correct CallableT type. Then, when you try to call, i use beginning of callable_ as pointer to ICallable. This all is standard safe.
Keep in mind, that you copy naive_function object, it's template argument T's copy operator is NOT called.
UPDATE: some improvements (at least try to force alignment) + addition of copying constructor / copy assignment.
My attempt to run the solution given Here, encountered with some issues. After fixing them, seems to work fine.
Will be happy for any review as I am not a c++ expert!
Issues and fixes:
error: lambda expression in an unevaluated operand.
removed the decltype. ( was not present in original code so I guess its safe(???)
using aligned_t = detail::aligned_union<0,
CallableT<void(*)()>,
//CallableT<decltype([]()->void {})>,
CallableT<void (CallableT<void(*)()>::*)()>
>;
Under C++11, errors in code block:
error: fields must have a constant size: 'variable length array in structure' extension will never be supported
error: 'aligned' attribute requires integer constant
error: constexpr variable 'alignment_value' must be initialized by a constant expression
(Note: this code is replacing std::aligned_union)
namespace detail {
template <size_t Len, class... Types>
struct aligned_union {
static constexpr size_t alignment_value = std::max({alignof(Types)...}); // ERROR HERE C++11
struct type {
alignas(alignment_value) char _s[std::max({Len, sizeof(Types)...})]; // ERROR HERE C++11
};
};
}
Used 'external' help from ETLCPP - which has support for embedded, file: largest.h.
Error block was replaced with :
#include"etl/largest.h"
template<typename ...Types>
using largest_t = typename etl::largest_type<Types...>::type;
namespace detail {
template <size_t Len, class... Types>
struct aligned_union {
static constexpr size_t alignment_value = etl::largest_alignment<Types...>::value; //std::max({alignof(Types)...});
struct type {
alignas(alignment_value) char _s[sizeof(largest_t<Types...>)]; //[std::max({Len, sizeof(Types)...})];
};
};
}
Looked redundant, removed:
//static constexpr size_t size() {
// auto f = []()->void {};
// return std::max(
// sizeof(CallableT<void(*)()>),
// std::max(
// sizeof(CallableT<decltype(f)>),
// sizeof(CallableT<void (CallableT<void(*)()>::*)()>)
// )
// );
//};
replaced std::forward with etl::forward file: utility.h
Had anew ,and delete errors : Undefined symbol operator delete
(void)*
So added ( I never allocate.. ):
// Define placement new if no new header is available
inline void* operator new(size_t, void* p) { return p; }
inline void* operator new[](size_t, void* p) { return p; }
inline void operator delete(void*, void*) {}
inline void operator delete[](void*, void*) {}
inline void operator delete[](void*) {}
Still getting a warning thought (???):
: warning: replacement function 'operator delete' cannot be declared 'inline' [-Winline-new-delete]
inline void operator delete(void* ) {}
Linker error:
Error: L6218E: Undefined symbol __cxa_pure_virtual ).
Probably because of virtual distractor : (ref)
virtual ~ICallable() = default;
Had to add this : ( any other solution ???)
extern "C" void __cxa_pure_virtual() { while (1); }
Related
I am trying to implement a pointer to member function wrapper where the return type and parameter types are known but the class type of the member function is not known. This is for a C++ project targeting resource constrained (No heap allocation/c++ standard library) microprocessor.
The following code seems to work (you can run it HERE) and it fulfills our general requirements, but it uses reinterpret_cast hackery.
//can't use any c++ std libs or heap allocation
#include <cstdio>
template<typename Ret,typename... Args>
struct member_cb
{
template<typename T>
void set_cb(T *obj_,Ret (T::*func)(Args...))
{
obj = reinterpret_cast<member_cb*>(obj_);
cb = reinterpret_cast<Ret (member_cb::*)(Args...)>(func);
}
Ret operator()(Args... num)
{
return (obj->*cb)(num...);
}
member_cb* obj;
Ret (member_cb::*cb)(Args...);
};
struct Bar{
void someFunc(int n2){
printf("someFunc called with parameter: %d\n",n2);
}
};
int main()
{
//class type of Bar is not known at wrapper creation
member_cb<void,int> foo;
Bar bar;
foo.set_cb(&bar, &Bar::someFunc);
foo(42);
}
I want to do this without the reinterpret_cast. I believe there is a solution using a lambda that is created by the set_cb() function something like this:
template<typename Ret,typename... Args>
struct member_cb
{
template<typename T>
void set_cb(T *obj_,Ret (T::*func)(Args...))
{
cb_func = [=](Args...num)
{
(obj_->*func)(num...);
};
}
Ret operator()(Args... args)
{
return cb_func(args...);
}
Ret (*cb_func)(Args...);
}
The above code will not compile (you can try it HERE). Problem is that the regular function pointers like cb_func can only point to lambdas that have no captures, and the lambda has to capture the obj_ and the func parameters. Any suggestions on making this work would be appreciated.
A simple, compiler-independent solution:
template <typename Signature>
struct member_cb;
template <typename Ret, typename... Args>
struct member_cb<Ret(Args...)>
{
template <typename T, Ret (T::*func)(Args...)>
static Ret wrapper(void *object, Args&&... args) {
T *o = reinterpret_cast<T *>(object);
return (o->*func)(std::forward<Args>(args)...);
}
template <typename T, Ret (T::*func)(Args...)>
void set_cb(T *obj_)
{
obj = obj_;
cb_func = wrapper<T, func>;
}
// since C++17:
template <auto func, typename T>
void set_cb(T *obj_)
{
obj = obj_;
cb_func = wrapper<T, func>;
}
Ret operator() (Args&& ...args)
{
return cb_func(obj, std::forward<Args>(args)...);
}
void *obj;
Ret (*cb_func)(void *, Args&&...);
};
...
member_cb<void(int)> foo;
foo.set_cb<Bar, &Bar::someFunc>(&bar);
foo.set_cb<&Bar::someFunc>(&bar); // since C++17
The key limitation is that someFunc must be known at compile-time at the place set_cb is called, so you can’t take arbitrary method pointer and convert it to a member_cb. It is possible to change the object keeping the method pointer intact, though (but that’s not type-safe).
Another possible problem is that the compiler may need to emit a wrapper instance for each and every method that is ever used as a callback.
The upside is that it should work on any C++11-compliant compiler (C++17 for nicer syntax), and member_cb itself is small.
As I understand, typedef cannot be used for overloading but what if I need to use some different types as arguments to the function pointer?
How can I make it work with the following functionality?
{
public:
typedef void (*InitFunc)(float x);
typedef void (*InitFunc)(int a, char b); //Needs to be added
virtual void initialize(InitFunc init) = 0;
};
Edit:
I cannot use C++17, so can't use variant
As commented, the easiest way is a union, although not very type safe and C++-y. Here is an example with inheritance, since you commented that you want inheritance.
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
union InitFn {
FloatInit fi;
IntCharInit ici;
};
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
f.fi(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
As mentioned by other commenters, you can use std::variant to enhance type safety and get rid of the manual union definition:
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
typedef std::variant<FloatInit, IntCharInit> InitFn;
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
std::get<FloatInit>(f)(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
One solution is to create a simple wrapper class template instead, to allow the compiler to automatically generate instantiations as necessary. This is relatively simple if init is always guaranteed to be a non-member function (and by extension, an actual function and not a functor/lambda).
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> {
public:
// Supply component types if needed.
// Tuple used for params, for convenience.
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
// Create from pointer or reference.
constexpr InitFunc(func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator func_ptr_type() { return ptr; }
operator func_ref_type() { return *ptr; }
private:
// Actual function pointer.
func_ptr_type ptr;
};
// And a nice, clean creator, which can be renamed as necessary.
template<typename Init>
constexpr auto make(Init func) { return InitFunc<Init>(func); }
This creates a nice little wrapper that can easily be optimised out entirely, and will compile as long as C++14 support is available.
Note that you require a C++11 compiler (or variadic templates, rvalue references, perfect forwarding, and constexpr support) at the absolute minimum, and will need to modify make() to have a trailing return type for pre-C++14 compilers. I believe this is compatible with C++11 constexpr, but I'm not 100% sure.
If you want InitFunc to be able to accept pointers/references-to-member-function (including functors and lambdas), you'll need to provide an additional version to isolate it into a non-member "function", and likely bind it to a class instance. It may be worth looking into std::bind() in this case, although I'm not sure if it has any overhead.
In this case, I would suggest splitting the member types off into a base class, to reduce the amount of code you'll need to duplicate.
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
// Supply component types if needed.
// Tuple used for params, for convenience.
// Using actual function type as a base, similar to std::function.
template<typename Ret, typename... Params>
class InitFunc<Ret(Params...)> {
public:
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
};
// Non-member functions.
// As member types are now dependent types, we qualify them and use `typename`.
// Yes, it looks just as silly as you think it does.
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> : public InitFunc<Ret(Params...)> {
// Actual function pointer.
typename InitFunc::func_ptr_type ptr;
public:
// Create from pointer or reference.
constexpr InitFunc(typename InitFunc::func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(typename InitFunc::func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr typename InitFunc::return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator typename InitFunc::func_ptr_type() { return ptr; }
operator typename InitFunc::func_ref_type() { return *ptr; }
};
// See ecatmur's http://stackoverflow.com/a/13359520/5386374 for how to accomodate member functions.
// ...
// Non-member function make() is unaffected.
// An overload will likely be needed for member functions.
template<typename Init>
auto make(Init func) { return InitFunc<Init>(func); }
Despite the awkwardness inside our derived specialisation, any code that relies on InitFunc shouldn't (to my knowledge) see any changes to its API; the previous example will work just fine if we swap to this new InitFunc, and be none the wiser after recompilation.
Note that it will change the ABI, though, and thus any code compiled for the simpler InitFunc will need to be recompiled for this version.
I'm making a class template to encode function pointers. The function can have any result type and number / type of parameters. This is what I have:
LPVOID EncodePtr(LPVOID ptr) {
// Encode...
return ptr;
}
LPVOID DecodePtr(LPVOID ptr) {
// Decode...
return ptr;
}
template<class T>
class encoded_ptr {
public:
typedef encoded_ptr<T> _Myt;
encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Irresponsible?
template<class _OtherType>
encoded_ptr(_OtherType ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
~encoded_ptr() {
ptr_ = (T*)EncodePtr(nullptr);
}
// Makes it possible to call the function directly
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
T* get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
T* ptr_;
};
It works as expected. Eg.:
encoded_ptr<decltype(MessageBoxA)> MsgBox;
MsgBox = &MessageBoxA; // Could also initialize in the constructor
// (HWND)0 is justified by the actual problem in the question
MsgBox((HWND)0, "Test message!", "Test", 0);
The first problem is that the way the parenthesis operator () is declared doesn't allow Visual Studio's IntelliSense to make its magic and give me hints about the function parameters:
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
Instead of using (_Args... _Ax), I'd like to unpack the actual function parameters so that IntelliSense can give hints correctly.
Current behaviour is:
Expected behaviour is:
The second problem is that calling the function this way, the compiler doesn't do basic casts, forcing me to cast NULL to (void*)NULL, 0 to (HWND)0, etc. This is annoying when using functions with a lot of parameters.
Maybe there are some mistakes in the implementation but I'm not a template expert. Also, I don't know if the title of the question fits properly.
I appreciate any help.
EDIT:
What I've tried so far (#OlegBogdanov's suggestion):
template<class T, class... Args>
class encoded_ptr;
template<class T, class... Args>
class encoded_ptr<T(Args...)> {
public:
typedef encoded_ptr<T> _Myt;
using Fptr = T(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (Fptr)EncodePtr((LPVOID)ptr);
}
// Makes it possible to call the function directly
typename T operator()(Args... _Ax) {
Fptr fn = get();
return fn(std::forward<Args>(_Ax)...);
}
Fptr get() const {
return (T*)DecodePtr((LPVOID)ptr_);
}
bool is_set() {
return (get() != nullptr);
}
private:
Fptr ptr_;
};
Result: Cannot instantiate / use the constructor: Incomplete type is not allowed.
EDIT:
That was the right direction, the problem was the calling convention.
Changed:
class encoded_ptr<T(Args...)> to class encoded_ptr<T(__stdcall)(Args...)>, and
using Fptr = T(*)(Args...) to using Fptr = T(__stdcall*)(Args...)
I'm trying to detect the calling convention instead of having it hardcoded.
I think your expectations of
template<class... _Args>
typename std::result_of<T*(_Args...)>::type operator()(_Args... _Ax) {
T* fn = get();
return fn(_Ax...);
}
are wrong. It completely ignore's your target functions argument list (you have used poor mans type erasure) and passes (I wanted to use word 'forwards' but that would be inaccurate) whatever caller gives in. Thus 0 in
MsgBox(0, "Test message!", "Test", 0);
is deduced as int and you have to cast it to HWND, there's no way compiler would guess it otherwise.
What you are really doing is re-inventing the std::function or sort of wrapper above it.
If you really think that std::function is not enough for your needs you will have to copy parts of its implementation, namely you would need to have at least
template<class R, class... Args>
class encoded_ptr; // leaving this undefined
template<class R, class... Args>
class encoded_ptr<R(Args...)> {
using Fptr = R(*)(Args...);
encoded_ptr(Fptr ptr) {
ptr_ = (T*)DecodePtr((LPVOID)ptr);
}
...
to capture argument list in your type
and call operator would re-use it instead of randomly typed passed arguments:
// this must not be here -> template<class... _Args>
R operator()(Args... _Ax) {
T* fn = get()
return fn(std::forward<Args>(_Ax)...);
}
Edit:
You can't store but T* anymore, T is just a return type, store by Fptr
I am looking for a way to convert function object to function pointer.
Captureless lambda has implicit conversion that allows to:
using fptr_t = int (*)(int);
fptr_t ptr = nullptr;
ptr = [](int) { return 2; };
ptr = [](auto) { return 3; };
(*ptr)(42);
I try to do the same with old-fashioned, empty class function objects like:
struct Foo {
int operator()(int) const { return 5; }
} foo;
Or std predicates like std::less<int>.
One way I found is to wrap call of foo with lambda.
If I can assure that foo is stateless and const
I dont really need this ptr and lambda-capture:
template <typename R, typename... Args>
struct to_function_pointer<R(Args...)> {
private:
template <typename T, REQUIRES(std::is_empty<T>::value)>
static T const& stateless_const() {
return (*static_cast<T const*>(nullptr));
}
public:
using pointer = R (*)(Args...);
template <typename U>
pointer operator()(U) const {
return [](Args... args) {
return stateless_const<std::decay_t<U>>()(args...);
};
}
};
But here I do not know how to provide perfect forwarding,
cause [](Args&&...) or [](auto&&...) cannot convert to R(*)(Args...).
Such trick fails when args is noncopyable like std::unique_ptr<int>.
I know that I could use std::function, but it's kind of heavy-weight, while I am trying to get a light-weight solution.
Live example.
Any advice appreciated.
I believe you can simplify your to_function_pointer with just:
template <typename R, typename... Args>
struct to_function_pointer<R(Args...)> {
using pointer = R(*)(Args...);
template <typename U, REQUIRES(std::is_empty<U>::value && std::is_trivially_constructible<U>::value)>
pointer operator()(U ) const
{
return [](Args... args) {
return U{}(std::forward<Args>(args)...);
}
}
};
Few things to note. Args... will already be references or not, you're providing that signature. So forward<> will still do the same thing - the function just happens to not be a template here. Also, scrap the weird nullptr cast. That just looks bad - if we just require trivial constructibility we can just write U{} which seems way cleaner to me.
I am using a class factory to create objects dynamically. I used this answer for its simplicity (and because I am using Qt).
But now I realize I must add an argument to my constructor
Item(bool newItem /* = true*/);
instead of
Item();
for the code in the referred answer:
template <typename T>
class ClassFactory
{
public:
template <typename TDerived>
void registerType(QString shape)
{
_createFuncs[shape] = &createFunc<TDerived>;
}
T* create(QString shape)
{
typename QMap<QString, PCreateFunc>::const_iterator it = _createFuncs.find(shape);
if (it != _createFuncs.end())
{
return it.value()();
}
return NULL;
}
private:
template <typename TDerived>
static T* createFunc()
{
return new TDerived();
}
typedef T* (*PCreateFunc)();
QMap<QString, PCreateFunc> _createFuncs;
};
I registered the class
classFactory.registerType <Type1_Item> ("type1");
when needed, I called
Item* item = classFactory.create("type1");
I am trying to add an additional argument in the class factory, to represent the constructor argument, but my attempts all result in error.
Why do I need it : simple case:
create a new object - sets defaults; for certain objects, it requires an open file dialog since data has to be loaded from a file.
load an object - fills data, including the filename for objects that contain file info
To be able to call the "load" function, an object must exist - which means that if I create a new object, I will trigger an open file dialog even though I do not need it.
The work around that I see is, to have a constructor followed by a setup function. But... that means constructing an object always requires a 2-function call, which seems like bad design.
that is why I am looking for a way to register and call the classes using simple calls like
classFactory.registerType <Type1_Item> ("type1", bool);
Item* item = classFactory.create("type1", true);
Is it possible, and how can I do it ?
The one way I can think of involves requiring that the arguments match exactly. First, we're going to store our functions using boost::any. This is because they may have different types, so we need a heterogenous container:
QMap<QString, boost::any> _createFuncs;
Our register function will create a specific function pointer to store in said any:
template <typename TDerived, typename... T>
void registerType(QString shape)
{
_createFuncs[shape] = &createFunc<TDerived, T...>;
}
where createFunc now takes extra arguments:
template <typename TDerived, typename... Args>
static T* createFunc(Args... args)
{
return new TDerived(args...);
}
The key is what we do on the creation side. We need to check to see if the any we have stored for the particular type is the right type:
template <typename... Args>
T* create(QString shape, Args... args)
{
using FPtr = T*(*)(Args...);
auto it = _createFuncs.find(shape);
if (it != _createFuncs.end())
{
// ok, it points to some any. is it the right any?
FPtr* fptr = boost::any_cast<FPtr>(&it.value());
if (fptr) {
return (*fptr)(args...);
}
// alternatively to the above, we can have createFunc
// throw bad_any_cast if you pass the wrong arguments
// which could be a loud, explicit failure rather than
// a silent one
return boost::any_cast<FPtr>(it.value())(args...);
}
return nullptr;
}
That will allow this to work:
classFactory.registerType<Item, bool>("type1");
^^^^^^
arg list
Item* item = classFactory.create("type1", true);
Item* item2 = classFactory.create<bool>("type1", 1);
But this will fail, since the any takes a bool, not an int:
Item* item3 = classFactory.create("type1", 1);
#Barry's answer is more than complete. However, if you are just interested in a simplified factory that can construct objects that have constructors taking different parameters, you can do something like:
// Factory method for classes having constructors
// that take an arbitary number of parameters
#include <memory>
class Factory
{
public:
template<typename T, typename... Params>
static std::unique_ptr<T> create(Params... params)
{
return std::make_unique<T>(params...);
}
};
struct Foo
{
Foo(int) {};
};
struct Bar
{
Bar(bool, double) {};
};
int main()
{
std::shared_ptr<Foo> foo = Factory::create<Foo>(42);
std::shared_ptr<Bar> bar = Factory::create<Bar>(true, 42.5);
}
Note that I used smart pointers here, so you don't need to keep track of new/deletes anymore.
You may use this modified version
template <typename T, typename ... Ts>
class ClassFactory
{
public:
template <typename TDerived>
void registerType(QString shape)
{
_createFuncs[shape] = &createFunc<TDerived>;
}
T* create(QString shape, Ts... args)
{
typename QMap<QString, PCreateFunc>::const_iterator it = _createFuncs.find(shape);
if (it != _createFuncs.end())
{
return it.value()(args...);
}
return nullptr;
}
private:
template <typename TDerived>
static T* createFunc(Ts... args)
{
return new TDerived(args);
}
typedef T* (*PCreateFunc)(Ts...);
QMap<QString, PCreateFunc> _createFuncs;
};
And use it
ClassFactory<Item, bool> classFactory;
classFactory.registerType <Type1_Item> ("type1");
Item* item = classFactory.create("type1", true);
If all the objects have the same parameter types (here a bool), just change the create function like this:
T* create(QString shape, bool param) //modified
{
typename QMap<QString, PCreateFunc>::const_iterator it = _createFuncs.find(shape);
if (it != _createFuncs.end())
{
return it.value()(param); //modified
}
return NULL;
}
And change createFunc also:
static T* createFunc(bool param)
{
return new TDerived(param);
}
typedef T* (*PCreateFunc)(bool);
I've done this using C++11 parameter packs:
// pack.cc
#include <utility>
template<class T, typename... P>
T * create(P&&... params)
{
return new T(std::forward<P>(params)...);
}
class X
{
public:
X() {}
};
class Y
{
public:
Y(int) {}
};
int main()
{
X * x = create<X>();
Y * y = create<Y>(1);
delete x;
delete y;
}
Compile this example g++ -std=c++11 -o pack pack.cc