Wrapping C functions in auto objects without code duplication - c++

In C++03, when you were to wrap a bunch of C functions in a class to create an 'auto object', you had to customize the object to the type of functions it encapsulated. As an example, to wrap a windows file HANDLE, you needed to call CloseHandle() in the destructor and CreateFile() in the constructor. The constructor would need to mimic the function signature of the CreateFile() function, sans the file HANDLE variable (since it's being managed).
Anyway, what I'd like to know is if it's possible to use the new features of C++11 to create a single generic class that can be used to wrap any type of resource by only providing an implementation for creation and deletion?
One problem I foresee is that the creation function, such as noted above with CreateFile(), can taken any number of parameters. Is there a way to auto-magically generate a templated constructor that mimics the signature of the function? Variadic Parameters come to mind, but I have not yet used them.
Has anyone tried writing something like this?
EDIT: Some code to help illustrate (pseudo):
template<typename Res, FunctionPtrToCreatorFunc Func, typename... Arguments>
class creator
{
public:
operator()(Res &r, Arguments... Args)
{
Func(r, /*use args?*/ Args); // Allocate resource, ie. CreateFile(r, args)
}
};
template<typename Res, FunctionPtrToDeleterFunc Func>
class deleter
{
operator()(Res &r)
{
Func(r); // delete the resource, ie. CloseHandle(r)
}
};
Then this will be the implementation of my super auto object:
template<typename Res, typename Creator, typename Deleter>
class auto_obj
{
public:
auto_obj(/*somehow copy Args from Creator class?*/)
{
Creator(_res, /*args?*/);
}
~auto_obj()
{
deleter(_res);
}
Res _res;
};
Yes, this has a similar structure to shared_ptr or unique_ptr, but instead the constructor will be the one that creates the resources by developer written creator and deleter classes. I have a feeling that std::bind may play a role in this, but I have never used it.

Here is a stab at it:
#include <utility>
#include <type_traits>
#include <cstddef>
A more friendly way to wrap up a function. I move the signature boilerplate to this template, instead of messing up the actual RAII class below. This also allows full fledged function objects to be used, as well as functions, in the RAII class below:
template< typename FuncSig, FuncSig func >
struct Functor {
template<typename... Args>
auto operator()(Args&&... args) const
-> decltype( func(std::forward<Args>(args)...) )
{ return ( func(std::forward<Args>(args)...) ); }
};
One operation that is needed for more than basic functionality is the ability to "null" a handle, allowing invalid handles to exist, and allowing handles to be moved around. Zeroer is my default function object for "null"ing a handle:
struct Zeroer {
template<typename T>
void operator()( T& t ) const {
t = 0;
}
};
RAII_handle herself. You pack the creation and destruction signatures into it, and it forwards construction to the underlying data. .close() lets you close the RAII_handle early, which is a common requirement in practice. You access the underlying data via operator* or operator->, and while this makes it look pointer-like, RAII_handle does not obey pointer semantics. It is a move-only type.
template< typename T, typename Creator, typename Destroyer, typename Nuller=Zeroer >
struct RAII_handle {
RAII_handle( std::nullptr_t ):
data()
{
Nuller()(data);
}
RAII_handle( RAII_handle const& ) = delete;
RAII_handle( RAII_handle && o ):data(std::move(o.data)) {
Nuller()(o.data);
}
RAII_handle& operator=( RAII_handle const& ) = delete;
RAII_handle& operator=( RAII_handle && o ) {
data = std::move(o.data);
Nuller()(o.data);
return *this;
}
template<typename... Args>
RAII_handle( Args&&... args ):
data( Creator()(std::forward<Args>(args)...) )
{}
auto close()->decltype( Destroyer()(std::declval<T&>()) ) {
auto retval = Destroyer()(data);
Nuller()(data);
return retval;
}
~RAII_handle() {
close();
}
T& get() { return data; }
T const& get() const { return data; }
T& operator*() { return get(); }
T const& operator*() const { return get(); }
T* operator->() { return &get(); }
T const* operator->() const { return &get(); }
private:
T data;
};
Now, some test code. My file handles will be unsigned char, and opening/closing will simply test if things are not working right.
#include <iostream>
typedef unsigned char HANDLE;
HANDLE CreateFile( char const* name ) {
std::cout << name << "\n";
return 7;
}
bool CloseFile( HANDLE h ) {
if (h) {
--h;
std::cout << (int)h << "\n";
return true;
} else {
std::cout << "already closed\n";
return true;
}
}
Once you have your open/close functions or function objects, here is how you make the type of the FileHandle:
typedef RAII_handle< HANDLE, Functor< HANDLE(*)( char const* ), CreateFile >, Functor< bool(*)(HANDLE), CloseFile > > FileHandle;
You can support entire overload sets by simply creating a function object that forwards to a fixed function name, instead of to a fixed function pointer. Basically take Functor above, remove the template signature and pointer, and replace the use of func with actual use of your function name.
Suddenly your function object represents not calling one function, but calling an entire overload set.
Fancier work can even support multiple functions, allowing one function object to support calling either CreateFile or CreateFileEx depending on what arguments are passed in.
And here is our trivial test code:
int main() {
FileHandle bob("hello.txt");
HANDLE value = *bob; // get the HANDLE out of the FileHandle
bob.close(); // optional, to close early
}
Requirements: your CloseFile must accept Nuller()(std::declval<T&>()) and not behave badly. The default Nuller()(...) just assigns zero to your T, which works for many handle types.
It supports move semantics, allowing you to return these from a function, but I didn't include a Copier argument (which I'd expect would be required for any RAII objects that can be copied).
Live example with very slightly different code.

Related

How do I pass an instance of a object function to another function?

I have a class that is trying to encapsulate the setup of an interrupt. I need to pass an instantiated reference/pointer/etc to an external function that then calls my function.
I can't change this function:
typedef void (*voidFuncPtr)(void);
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
My Library:
class Buttons ...
bool Buttons::begin(int buttonPin)
{
//attachInterrupt(buttonPin, (this->*func)Buttons::released, HIGH);
attachInterrupt(buttonPin, &Buttons::released, LOW);
return 0;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
The problem is that I don't know what to put inside the attachInterupt function in the Buttons::begin method. I am sure I am doing something wrong in the way I am approaching this problem, but I am not sure what it is or what I should do about it. I would greatly appreciate any suggestions!
You're using an old c-style function pointer callback. This does not work for member function of an object. If you can't change the callback, you need to make the Buttons::released function static.
The problem you were facing is that you wanted to pass two pieces of data as your callback: the member function, and a class instance to call that member function on.
With the existing interface, which only accepts a function pointer with no arguments, you might create a static Button object and then write a static wrapper function that calls someStaticButton.released(). Then you could pass the address of this wrapper function as your callback. Justin Time’s answer approaches from a different, and clever, direction: wrap the instance and member in a singleton class, and give that a static member callback function. A simpler way to allow more than one singleton class would be to add a numeric ID as template parameter.
You might also be able to make button::released() a static member function, but your implementation appears to refer to member data. This wouldn’t be an option unless there is only one button in the program, represented by a singleton class.
If you can pass the instance pointer as the first argument to your callback function, or any other argument that can do a round-trip conversion to and from an object pointer (such as void* or any integer as wide as intptr_t), you can make the member function static and pass the this pointer as its argument.
If you can overload attachInterrupt to take a std::function object as your callback, you can do what you originally wanted. This type can represent a static function, a member function, or a closure containing a member function and a this pointer.
You unfortunately say you cannot change the callback function, but perhaps you can extend the interface in a backward-compatible way, such as:
#include <array>
#include <iostream>
#include <functional>
#include <stdint.h>
#include <stdlib.h>
#include <utility>
using std::cout;
using std::endl;
using voidFuncPtr = void(*)(void);
using Callback = std::function<void(void)>;
std::array<Callback, 1> interrupts;
void attachInterruptEx( const uint32_t pin,
Callback&& callback,
const uint32_t /* unused */ )
{
interrupts.at(pin) = std::move(callback);
}
void attachInterrupt( const uint32_t pin,
const voidFuncPtr callbackPtr,
const uint32_t mode )
{
/* Passing callbackPtr to a function that expects Callback&& implicitly
* invokes the constructor Callback(voidFuncPtr). This is sugar for
* std::function<void(void)>(void(*)(void)). That is, it initializes a
* temporary Callback object from callbackPtr.
*/
return attachInterruptEx( pin, callbackPtr, mode );
}
class Buttons {
public:
Buttons() = default;
bool begin(int buttonPin);
void released();
unsigned long buttonPresses() { return numButtonPresses; }
private:
// Empty stub function, probably calls a timer.
unsigned long millis() { return 0; };
static constexpr uint32_t LOW = 0;
uint32_t buttonState = LOW;
unsigned long numButtonPresses = 0;
unsigned long pressStartTime = 0;
unsigned long pressLength = 0;
};
/* Per C++17, a constant known at compile time is not odr-used, so this
* definition is deprecated. Still included out of an abundance of caution.
* It cannot have an initializer.
*/
constexpr uint32_t Buttons::LOW;
bool Buttons::begin(int buttonPin)
{
/* The C++17 Standard says little about the return type of std::bind().
* Since the result is a callable object, a std::function can be initialized
* from it. I make the constructor call explicit in case the return type of
* std::bind is a subclass of std::function in some implementation, and
* it resolves the overload in a way we don't expect.
*/
attachInterruptEx( static_cast<uint32_t>(buttonPin),
Callback(std::bind(&Buttons::released, this)),
LOW );
return false;
}
void Buttons::released()
{
numButtonPresses++;
pressLength = millis()-pressStartTime;
pressStartTime = 0;
buttonState=LOW;
}
int main(void)
{
Buttons buttons;
buttons.begin(0);
interrupts[0]();
// Should be 1.
cout << buttons.buttonPresses() << endl;
return EXIT_SUCCESS;
}
[Note that this code will use the following simplified version of your MCVE, primarily to have an easily-usable callback caller when testing & demonstrating the implementation:]
// Pointer type.
typedef void (*voidFuncPtr)(void);
// Dummy callback callers.
void takesVoidFuncPtr(voidFuncPtr vfp) {
std::cout << "Now calling vfp...\n";
vfp();
std::cout << "vfp called.\n";
}
struct DelayedCaller {
voidFuncPtr ptr;
DelayedCaller(voidFuncPtr p) : ptr(p) {}
void callIt() { return ptr(); }
};
// Simple stand-in for Button.
struct HasMemberFunction {
std::string name;
HasMemberFunction(std::string n) : name(std::move(n)) {}
void memfunc() { std::cout << "-->Inside " << name << ".memfunc()<--\n"; }
void funcmem() { static std::string out("Don't call me, I'm lazy. >.<\n"); std::cout << out; }
};
// Calling instance.
HasMemberFunction hmf("instance");
Ideally, you'd be able to bind the function to an instance with a lambda, and pass that to the consuming function as the callback. Unfortunately, though, capturing lambdas can't be converted to non-member function pointers, so this option isn't viable. However...
[Note that I have omitted proper encapsulation both for brevity, and for a demonstration of this approach's caveats at the end of the answer. I would recommend adding it if you actually use this.]
// Helper.
// Can easily be simplified if desired, Caller and MultiCaller only use FuncPtrTraits::ContainingClass.
namespace detail {
template<typename...> struct Pack {};
template<typename T> struct FuncPtrTraits;
template<typename Ret, typename Class, typename... Params>
struct FuncPtrTraits<Ret (Class::*)(Params...)> {
using ReturnType = Ret;
using ContainingClass = Class;
using ParameterList = Pack<Params...>;
};
template<typename T>
using ContainingClass = typename FuncPtrTraits<T>::ContainingClass;
} // detail
// Calling wrapper.
// Only allows one pointer-to-member-function to be wrapped per class.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>>
struct Caller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static Class* c;
static MemFunc mf;
static void prep(Class& cls, MemFunc mem) { c = &cls; mf = mem; }
static void clean() { c = nullptr; mf = nullptr; }
static void call() { return (c->*mf)(); }
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. ...Probably best not to do this. ;3
Caller(Class& cls, MemFunc mem) { prep(cls, mem); }
// Default constructor is required if we provide the above hax ctor.
Caller() = default;
};
template<typename MemFunc, typename Class> Class* Caller<MemFunc, Class>::c = nullptr;
template<typename MemFunc, typename Class> MemFunc Caller<MemFunc, Class>::mf = nullptr;
We can instead provide the desired behaviour by using a wrapper class, which stores the desired function and instance as static member variables, and provides a static member function that matches voidFuncPtr and contains the actual, desired function call. It can be used like so:
std::cout << "\nSimple caller, by type alias:\n";
using MyCaller = Caller<decltype(&HasMemberFunction::memfunc)>;
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&MyCaller::call);
MyCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nSimple caller, via dummy instance:\n";
Caller<decltype(&HasMemberFunction::memfunc)> caller;
caller.prep(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&caller.call);
caller.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
That's a bit of a mess, so a hacky constructor is provided to simplify it.
[Note that this may violate the principle of least astonishment, and thus isn't necessarily the best option.]
std::cout << "\nSimple caller, via hax ctor:\n";
Caller clr(hmf, &HasMemberFunction::memfunc);
takesVoidFuncPtr(&clr.call);
clr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Now, this version only allows one function to be wrapped per class. If multiple functions per class are required, we'll need to expand it a little.
[Note that this would be pretty awkward to typedef, as the optimal template parameter order places the first pointer-to-member-function first, to allow Class to be automatically deduced if only one function needs to be wrapped; the "hax ctor" approach was primarily intended for this version of Caller, although a deduction guide could likely also be used to swap Class and MemFunc.]
[Also note that all wrapped member functions must have the same signature.]
// Calling wrapper.
// Slightly more complex version, allows multiple instances of MemFunc to be wrapped.
template<typename MemFunc, typename Class = detail::ContainingClass<MemFunc>, typename... MemFuncs>
struct MultiCaller {
static_assert(std::is_member_function_pointer<MemFunc>::value, "Must be built with pointer-to-member-function.");
static_assert(std::conjunction_v<std::is_same<MemFunc, MemFuncs>...>, "All pointers-to-member-function must be the same type.");
static Class* c;
static std::array<MemFunc, 1 + sizeof...(MemFuncs)> mfs;
static void prep(Class& cls, MemFunc mem, MemFuncs... mems) { c = &cls; mfs = { mem, mems... }; }
static void clean() { c = nullptr; for (auto& m : mfs) { m = nullptr; } }
// Registered functions are wrapped by index, with index specified as a template parameter to match empty parameter list.
template<size_t N = 0, bool B = (N < mfs.size())>
static void call() {
static_assert(B, "Index must be a valid index for mfs.");
return (c->*mfs[N])();
}
// Constructor is provided for convenience of creation, to effectively tie prep() to deduction guide.
// Note that it operates on static members only.
// Convenient, but likely confusing. Primarily used because instantiation & preparation get really repetitive otherwise.
MultiCaller(Class& cls, MemFunc mem, MemFuncs... mems) { prep(cls, mem, mems...); }
// Default constructor is required if we provide the above hax ctor.
MultiCaller() = default;
};
template<typename MemFunc, typename Class, typename... MemFuncs> Class* MultiCaller<MemFunc, Class, MemFuncs...>::c = nullptr;
template<typename MemFunc, typename Class, typename... MemFuncs> std::array<MemFunc, 1 + sizeof...(MemFuncs)> MultiCaller<MemFunc, Class, MemFuncs...>::mfs = {nullptr};
It can be used by type alias as before, or the "hax ctor" can be used to couple it to a deduction guide like so:
std::cout << "\nMulti-registration caller, by type alias:\n";
using MyMultiCaller = MultiCaller<decltype(&HasMemberFunction::memfunc), HasMemberFunction, decltype(&HasMemberFunction::funcmem)>;
MyMultiCaller::prep(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&MyMultiCaller::call<0>); // memfunc
takesVoidFuncPtr(&MyMultiCaller::call<1>); // funcmem
MyMultiCaller::clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
// Or...
std::cout << "\nMulti-registration caller, via hax ctor:\n";
MultiCaller mclr(hmf, &HasMemberFunction::memfunc, &HasMemberFunction::funcmem);
takesVoidFuncPtr(&mclr.call<0>); // memfunc
takesVoidFuncPtr(&mclr.call<1>); // funcmem
mclr.clean(); // Not strictly necessary, but may be useful once the callback will no longer be called.
Note that in all cases, this has all the caveats of static members. In particular, since the binding relies on the static class members and isn't contained within the wrapper function itself, modifying the members after a callback is passed will immediately change the results of calling said already-passed callback.
std::cout << "\nBut alas:\n";
MyCaller::prep(hmf, &HasMemberFunction::memfunc);
DelayedCaller dc(&MyCaller::call);
dc.callIt(); // Output: "-->Inside instance.memfunc()<--"
std::cout << "Changing the registered instance will...\n";
HasMemberFunction hmf2("spinstance");
MyCaller::c = &hmf2;
dc.callIt(); // Output: "-->Inside spinstance.memfunc()<--"
You can see the different variants here, on Compiler Explorer.

Getting around the lack of templated virtual functions in C++

I'm not sure how best to phrase the question, but I'm not asking how to implement templated virtual functions per-se. I'm building an entity component system, and I have two important classes - World and Entity. World is actually an abstract class, and the implementation (let's call it WorldImpl) is a templated class that allows use of a custom allocator (one that can be used with std::allocator_traits).
Components are any data type which we can attach to entities. This is done by calling a templated function named assign on the entity.
Here's the problem: I'm trying to make the entity use the world's allocator when creating and initializing components. In a perfect world, you would call Entity::assign<ComponentType>( ... ) which would ask the WorldImpl to create the component with whatever allocator is appropriate. There's a problem here, however - The entity has a pointer to World and templated virtual functions aren't possible to my knowledge.
Here's a bit more of an illustration that might make the issue more obvious:
class Entity
{
template<typename ComponentType>
void assign(/* ... */)
{
/* ... */
ComponentType* component = world->createComponent<ComponentType>(/* ... */);
/* ... */
}
World* world;
};
// This is the world interface.
class World
{
// This is the ideal, which isn't possible as it would require templated virtual functions.
template<typename ComponentType>
virtual ComponentType* createComponent(/* ... */) = 0;
};
template<typename Allocator>
class WorldImpl : public World
{
template<typename ComponentType> // again, not actually possible
virtual ComponentType* createComponent(/* ... */)
{
// do something with Allocator and ComponentType here
}
};
Seeing as the above code isn't actually possible, here's the real question: With a class hierarchy such as this, what black magic do I have to do in order for some function to be called with both the ComponentType and Allocator template parameters? This is the ultimate goal - a function called on some object with both template parameters available to it.
I'd say that Entities belong to a certain kind of world and make them templates with a World parameter. Then you can forget about all the inheritance and virtual and just implement worlds that fulfill the required interface, e.g.
template<typename World>
class Entity
{
template<typename ComponentType>
void assign(/* ... */)
{
/* ... */
ComponentType* component = world.createComponent<ComponentType>(/* ... */);
/* ... */
}
World world;
};
template<typename Allocator>
class WorldI
{
template<typename ComponentType>
ComponentType* createComponent(/* ... */)
{
// do something with Allocator and ComponentType here
}
};
Note that this isn't an optimal solution (see the bottom of the post for issues), but a somewhat-viable way to combine templates and virtual functions. I post it in the hopes that you can use it as a basis to come up with something more efficient. If you can't find a way to improve on this, I would suggest templating Entity, as the other answer suggested.
If you don't want to do any major modifications to Entity, you can implement a hidden virtual helper function in World, to actually create the component. In this case, the helper function can take a parameter which indicates what kind of component to construct, and return void*; createComponent() calls the hidden function, specifying ComponentType, and casts the return value to ComponentType*. The easiest way I can think of is to give each component a static member function, create(), and map type indexes to create() calls.
To allow each component to take different parameters, we can use a helper type, let's call it Arguments. This type provides a simple interface while wrapping the actual parameter list, allowing us to easily define our create() functions.
// Argument helper type. Converts arguments into a single, non-template type for passing.
class Arguments {
public:
struct ArgTupleBase
{
};
template<typename... Ts>
struct ArgTuple : public ArgTupleBase {
std::tuple<Ts...> args;
ArgTuple(Ts... ts) : args(std::make_tuple(ts...))
{
}
// -----
const std::tuple<Ts...>& get() const
{
return args;
}
};
// -----
template<typename... Ts>
Arguments(Ts... ts) : args(new ArgTuple<Ts...>(ts...)), valid(sizeof...(ts) != 0)
{
}
// -----
// Indicates whether it holds any valid arguments.
explicit operator bool() const
{
return valid;
}
// -----
const std::unique_ptr<ArgTupleBase>& get() const
{
return args;
}
private:
std::unique_ptr<ArgTupleBase> args;
bool valid;
};
Next, we define our components to have a create() function, which takes a const Arguments& and grabs arguments out of it, by calling get(), dereferencing the pointer, casting the pointed-to ArgTuple<Ts...> to match the component's constructor parameter list, and finally obtaining the actual argument tuple with get().
Note that this will fail if the Arguments was constructed with an improper argument list (one that doesn't match the component's constructor's parameter list), just as calling the constructor directly with an improper argument list would; it will accept an empty argument list, however, due to Arguments::operator bool(), allowing default parameters to be provided. [Unfortunately, at the moment, this code has issues with type conversion, specifically when the types aren't the same size. I'm not yet sure how to fix this.]
// Two example components.
class One {
int i;
bool b;
public:
One(int i, bool b) : i(i), b(b) {}
static void* create(const Arguments& arg_holder)
{
// Insert parameter types here.
auto& args
= static_cast<Arguments::ArgTuple<int, bool>&>(*(arg_holder.get())).get();
if (arg_holder)
{
return new One(std::get<0>(args), std::get<1>(args));
}
else
{
// Insert default parameters (if any) here.
return new One(0, false);
}
}
// Testing function.
friend std::ostream& operator<<(std::ostream& os, const One& one)
{
return os << "One, with "
<< one.i
<< " and "
<< std::boolalpha << one.b << std::noboolalpha
<< ".\n";
}
};
std::ostream& operator<<(std::ostream& os, const One& one);
class Two {
char c;
double d;
public:
Two(char c, double d) : c(c), d(d) {}
static void* create(const Arguments& arg_holder)
{
// Insert parameter types here.
auto& args
= static_cast<Arguments::ArgTuple<char, double>&>(*(arg_holder.get())).get();
if (arg_holder)
{
return new Two(std::get<0>(args), std::get<1>(args));
}
else
{
// Insert default parameters (if any) here.
return new Two('\0', 0.0);
}
}
// Testing function.
friend std::ostream& operator<<(std::ostream& os, const Two& two)
{
return os << "Two, with "
<< (two.c == '\0' ? "null" : std::string{ 1, two.c })
<< " and "
<< two.d
<< ".\n";
}
};
std::ostream& operator<<(std::ostream& os, const Two& two);
Then, with all that in place, we can finally implement Entity, World, and WorldImpl.
// This is the world interface.
class World
{
// Actual worker.
virtual void* create_impl(const std::type_index& ctype, const Arguments& arg_holder) = 0;
// Type-to-create() map.
static std::unordered_map<std::type_index, std::function<void*(const Arguments&)>> creators;
public:
// Templated front-end.
template<typename ComponentType>
ComponentType* createComponent(const Arguments& arg_holder)
{
return static_cast<ComponentType*>(create_impl(typeid(ComponentType), arg_holder));
}
// Populate type-to-create() map.
static void populate_creators() {
creators[typeid(One)] = &One::create;
creators[typeid(Two)] = &Two::create;
}
};
std::unordered_map<std::type_index, std::function<void*(const Arguments&)>> World::creators;
// Just putting in a dummy parameter for now, since this simple example doesn't actually use it.
template<typename Allocator = std::allocator<World>>
class WorldImpl : public World
{
void* create_impl(const std::type_index& ctype, const Arguments& arg_holder) override
{
return creators[ctype](arg_holder);
}
};
class Entity
{
World* world;
public:
template<typename ComponentType, typename... Args>
void assign(Args... args)
{
ComponentType* component = world->createComponent<ComponentType>(Arguments(args...));
std::cout << *component;
delete component;
}
Entity() : world(new WorldImpl<>())
{
}
~Entity()
{
if (world) { delete world; }
}
};
int main() {
World::populate_creators();
Entity e;
e.assign<One>();
e.assign<Two>();
e.assign<One>(118, true);
e.assign<Two>('?', 8.69);
e.assign<One>('0', 8); // Fails; calls something like One(1075929415, true).
e.assign<One>((int)'0', 8); // Succeeds.
}
See it in action here.
That said, this has a few issues:
Relies on typeid for create_impl(), losing the benefits of compile-time type deduction. This results in slower execution than if it was templated.
Compounding the issue, type_info has no constexpr constructor, not even for when the typeid parameter is a LiteralType.
I'm not sure how to obtain the actual ArgTuple<Ts...> type from Argument, rather than just casting-and-praying. Any methods of doing so would likely depend on RTTI, and I can't think of a way to use it to map type_indexes or anything similar to different template specialisations.
Due to this, arguments must be implicitly converted or casted at the assign() call site, instead of letting the type system do it automatically. This... is a bit of an issue.

factory, unique_ptr and static_cast

Consider polymorphic classes with a base object, a derived interface, and a final object:
// base object
struct object
{
virtual ~object() = default;
};
// interfaces derived from base object
struct interface1 : object
{
virtual void print_hello() const = 0;
template<typename T>
static void on_destruction(object* /*ptr*/)
{
std::cout << "interface1::on_destruction" << std::endl;
}
};
// final object
struct derived1 : interface1
{
virtual void print_hello() const override
{
std::cout << "hello" << std::endl;
}
static std::string get_type_name()
{
return "derived1";
}
};
In the real use case, final objects are defined through a plugin system, but that is not the point. Note that I want to be able to call on_destruction when an object is destroyed (see register_object below). I want to use these classes as follows:
int main()
{
// register derived1 as an instantiable object,
// may be called in a plugin
register_object<derived1>();
// create an instance using the factory system
auto instance = create_unique<interface1>("derived1");
instance->print_hello();
return 0;
}
Using std::unique_ptr to manage the objects, I ended up with the following code for register_object:
template<typename T>
using unique = std::unique_ptr<
T,
std::function<void(object*)> // object deleter
>;
namespace
{
std::map< std::string, std::function<unique<object>(void)> > factory_map;
}
template<typename T>
void register_object()
{
factory_map.emplace(
T::get_type_name(),
[]()
{
unique<T> instance{
new T,
[](object* ptr)
{
T::on_destruction<T>(ptr);
delete ptr;
}
};
return static_move_cast<object>(
std::move(instance)
);
}
);
}
And the create* functions:
unique<object> create_unique_object(const std::string& type_name)
{
auto f = factory_map.at(type_name);
return f();
}
template<typename T>
unique<T> create_unique(const std::string& type_name)
{
return static_move_cast<T>(
create_unique_object(type_name)
);
}
You noticed in register_object and create_unique the call to static_move_cast, which is declared as:
template<typename U, typename T, typename D>
std::unique_ptr<U, D>
static_move_cast
(
std::unique_ptr<T, D>&& to_move_cast
)
{
auto deleter = to_move_cast.get_deleter();
return std::unique_ptr<U, D>{
static_cast<U*>(
to_move_cast.release()
),
deleter
};
}
The goal behind static_move_cast is to allow static_cast on std::unique_ptr while moving the deleter during the cast. The code is working, but I feel like hacking std::unique_ptr. Is there a way to refactor the code to avoid my static_move_cast?
static_move_cast is unnecessary within register_object, since you can just use the converting constructor of unique_ptr template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ):
unique<T> instance{
new T,
// ...
};
return instance;
Or, even simpler, construct and return a unique<object> directly, since T* is convertible to object*:
return unique<object>{
new T,
// ...
};
However for create_unique the use of static_move_cast is unavoidable, since the converting constructor of unique_ptr won't work for downcasts.
Note that shared_ptr has static_pointer_cast, which performs downcasts, but there is no corresponding facility for unique_ptr, presumably because it it is considered straightforward and correct to perform the cast yourself.
I would say it is good solution given the requirements. You transfer the responsibility to the caller of create_unique. He must give correct combination of type and string and string that is in the registry.
auto instance = create_unique<interface1>("derived1");
// ^^^^^^^^^^ ^^^^^^^^
// what if those two don't match?
You could improve it a bit by changing the static_cast to dynamic_cast. And the caller of create_unique should always check that he got non-null pointer before calling anything on it.
Or at least use dynamic_cast with assert in debug mode, so you catch mismatches while developing.
Alternative refactoring: Have separate factory for every existing interface.

How to write a template function that can handle object or pointer function calls ?

I would like to be able to write a template function that can invoke a function call on all elements of a container. We can assume that the function name is always the same. However what isn't known is whether the container is holding objects or pointers. ie, whether I should de-reference.
template< typename TContainer >
void ProcessKeyedContainer( TContainer &keyedContainer )
{
for ( auto it = keyedContainer.begin(); it != keyedContainer.end(); ++it )
{
// do some random stuff here.
// ...
auto value = it->second;
value.Process(); // or value->Process() if the container has pointers
}
}
...
std::map< int, CMyObject > containerOfObjects;
containerOfObjects[0] = CMyObject();
std::map< int, CMyObject* > containerOfPointers;
containerOfPointers[0] = new CMyObject();
// I would like both calls to look near identical
ProcessKeyedContainer( containerOfObjects );
ProcessKeyedContainer( containerOfPointers );
Is there a neat way to be able to make the Process call inside ProcessKeyedContainer, without putting a burden on the caller ( ie the caller doesn't have to know to use it in one way for pointers and another way for objects ), and without having to duplicate too much code ?
Overloaded function template is the savior:
template<typename T>
void invoke(T * obj) //when object is pointer
{
obj->Process();
}
template<typename T>
void invoke(T & obj) //when object is non-pointer
{
obj.Process();
}
then use it as:
auto value = it->second;
invoke(value); //correct invoke() will be selected by the compiler!
But that is not good enough, as you might want to do something else also with value in the rest of the function written by you. So if you follow the above approach, there will be code duplication, as both invoke() will have almost similar code.
So here is one improvement: instead of using invoke(), turn the pointer into reference so that you could use it uniformly in your function.
template<typename T>
T& ensure_ref(T * obj) //when object is pointer
{
return *obj; //return the dereferenced object
}
template<typename T>
T& ensure_ref(T & obj) //when object is non-pointer
{
return obj; //simply return it
}
And use it as:
auto & value = ensure_ref(it->second); //call ensure_ref to ensure reference!
value.Process(); //value is gauranteed to be NOT pointer!
//you might want to do this also!
value.xyz = abc;
Hope that helps!

boost::bind with null function pointers

If the function pointer embedded in a boost::bind return object is NULL/nullptr/0, I need to take action other than calling it. How can I determine if the object contains a null function pointer?
Addenda
I don't believe I can use and compare boost::functions as the boost::bind return object is used with varying call signatures in a template function.
Simplified example:
template <typename BRO>
Retval do_stuff(BRO func, enum Fallback fallback)
{
if (func == NULL)
{
return do_fallback(fallback);
}
else
{
return use_retval(func());
}
}
do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), fallback);
Solution
Since the arity of the function in the callee does not change, I can "cast" the bind return object into a boost::function and call .empty()
Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback)
{
if (func.empty())
return do_fallback(fallback);
else
return use_retval(func());
}
You can either bind to a dummy function:
void dummy() { /* has differing behaviour */ }
// ...
boost::bind(&dummy)();
... or, assuming you're using Boost.Bind together with Boost.Function, return a default constructed function object and check for empty() before calling it:
typedef boost::function<void (void)> F;
F create() { return F(); }
void use() {
F f = create();
if(f.empty()) {
/* ... */
}
}
Regarding the update:
I still don't see what the problem with binding to a different function like the following would be:
template <typename BRO>
Retval do_stuff(BRO func)
{
return func();
}
if(funcPtr) {
do_stuff(boost::bind(&use_retval, boost::bind(funcPtr, a, b)));
} else {
do_stuff(boost::bind(&do_fallback, fallback));
}
If you'd want to move that handling out of the calling code, you could emulate variadic template function to support variable arities:
template<class R, class T1>
boost::function<R (T1)>
bind_wrap(R (*fnPtr)(), T1& t1, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1));
else return boost::bind(&do_fallback, fallback);
}
template<class R, class T1, class T2>
boost::function<R (T1, T2)>
bind_wrap(R (*fnPtr)(T1, T2), T1& t1, T2& t2, Fallback fallback) {
if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1, t2));
else return boost::bind(&do_fallback, fallback);
}
// ... etc. for all needed arities
do_stuff(bind_wrap(funcPtr, var1, var2, fallback));
... or you use the approach above to generate boost::function<> objects or your own wrappers and check for functor.empty() or similar in do_stuff().
I'd create a wrapper object to do this. Something like the following
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
int aFunction(int i, int j)
{
std::cout<<"In a Function"<<std::endl;
return i+j;
}
struct DefaultingFromFnPtr : public boost::function< int(int,int) >
{
explicit DefaultingFromFnPtr( int(*fn)(int,int) ) : fn_(fn) {}
int operator()(int i, int j) const
{
if (fn_!=NULL) return fn_(i, j);
return 7;
}
int(*fn_)(int,int);
};
template<typename T>
void do_stuff( T t )
{
std::cout<<"RETURNED "<<t()<<std::endl;
}
int main( int argv, const char** argc)
{
int(*mightBeNullFnPtr)(int,int) = NULL;
if( argv>1)
{
mightBeNullFnPtr = & aFunction;
}
int var1 = 10;
int var2 = 20;
do_stuff( boost::bind( DefaultingFromFnPtr( mightBeNullFnPtr ), var1, var2 ) );
}
Compile this and run it with no arguments and it sets mightBeNullFnPtr to NULL and calls do_stuff with a wrapper class, and so prints out 7. Run it with an argument and it will set mightByNullFnPtr to aFunction and calls do_stuff with that, printing out 30.
If you want more genericity you will need to template the DefaultingFromFnPtr wrapper class, but that should be pretty easy to do.
I'm pretty sure calling boost::bind with a null pointer (= the creation of the bind object) should be considered undefined behavior, even if the crash only happens when calling it.
You're going to have to hack boost.
boost::bind returns unspecified-n-n. The only thing valid to do with these classes is operator(). The only other thing you know is that they are copy constructable, and have a typedef for result_type (which, by the way, means you don't need a template for result type).
You want something else - so you'll need to find the definition of unspecified-n-n in boost (there maybe several), hack them to have a is_null() member function which checks for the conditions you want, then call that as your test.
This is, of course, assuming you are certain you'll always get a boost::bind'ed object in your template function. If someone tries passing in a regular function pointer, it won't compile. Working around this will require some template magic.