i need to store pointers to instanced template functions and when function cannot be instanced i would like to store pointer to empty function instead. I looked into SFINAE but i dont think it applies here.
struct StaticEntity {
double position;
};
struct DynamicEntity {
double position;
double speed;
};
class MoveSystem {
public:
template <typename T>
void update(T& entity, double dt) {
entity.position += entity.speed*dt;
}
};
typedef void (*updateEntitiesFunc)(void* system, void* entity, double dt);
template <typename S, typename E>
static void update(void* system, void* entity, double dt)
{
// here if inner function cannot be instanced i would like to skip it and do "nothing" instead
((S*)system)->update(*(E*)entity, dt);
}
int main() {
updateEntitiesFunc uf = update<MoveSystem, DynamicEntity>;
updateEntitiesFunc uf2 = update<MoveSystem, StaticEntity>;
//^ this does not compile
// gives error: 'struct StaticEntity' has no member named 'speed'
// i would like it to compile and contain pointer to empty function
return 0;
}
It probably is solvable with some template magic that i just cant figure out.
Ideally without adding complexity to both Entity and System classes.
Design motivation:
for all my entity and system types i want to create a static array of function pointers:
updateEntitiesFunc funcs[EntityTypes::getTypesCount()][SystemTypes::getTypesCount()];
And then at runtime call correct function with type-ids:
funcs[entity->getTypeId()][system->getTypeId()](&system, &entity, dt);
At runtime i will check if entity is compatible with system but it is runtime information. So all function pointers must be registered for all entity-system pairs at compile time, even though they are not compatible. This is where i wanted to create those no-op functions.
First, metaprogramming boilerplate:
namespace details {
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class, class...Ts>
struct can_apply:
std::false_type
{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:
std::true_type
{};
}
template<template<class...>class Z, class...Ts>
using can_apply=details::can_apply<Z,void,Ts...>;
Now, we can detect properties:
template<class T>
using speed_t = decltype(std::declval<T>().speed);
template<class T>
using position_t = decltype(std::declval<T>().position);
template<class T>
using has_speed = can_apply<speed_t, T>;
template<class T>
using has_position = can_apply<position_t, T>;
template<class S, class E>
using update_call_t = decltype( std::declval<S>().update( std::declval<E>(), 0.0 ) );
template<class S, class E>
using has_update = can_apply< update_call_t, S, E >;
and we have three traits, has_position, has_update and has_speed that are useful.
Now we fix MoveSystem:
struct MoveSystem {
template <class T>
std::enable_if_t< has_speed<T&>{} && has_position<T&>{} >
update(T& entity, double dt) {
entity.position += entity.speed*dt;
}
};
next, we modify update:
namespace updates {
template<class S, class E>
std::enable_if_t< has_update<S,E>{} >
update(S* system, E* entity, double dt ) {
system->update(*entity, dt);
}
void update(void*, void*, double) {}
}
template<class S, class E>
void update(void* system, void* entity, double dt) {
using updates::update;
update(static_cast<S*>(system), static_cast<E*>(entity), dt );
}
to check for the .update method working with those parameters.
I ADL-enabled the code such that if the class has a friend void update( S*, E*, double ) it will also work.
This is all SFINAE work. Note that adding more properties once we have can_apply is pretty easy. Make an alias that generates a type that only works if the property is satisfied, then write a can_apply alias that converts that application to a compile-time boolean test.
As an aside, MSVC2015 is not a C++11 compiler, in that it cannot compile the above code. In MSVC you have to track down some proprietary extensions to do the equivalent of the above code. This involves writing has_position and the other traits differently. They call the failure to obey the C++11 standard in this case an inability to do "expression SFINAE".
Note that the above uses a handful of C++14 features. Replace std::enable_if_t<??> with typename std::enable_if<??>::type, replace has_position<??>{} with has_position<??>::value and similar other changes if your compiler doesn't support it.
Related
I have a class template that has members of some type. This type is determined based on the type that is provided when instantiating the template. It uses a default (double in the example below) unless an override is provided by that class. Classes used as template types may provide this override type (here "Two" provides the override type "int"). If a class provides the override, the override should only be used if the class also sets the UseOverride flag. If flag is absent or false, default "double" should be used.
Problem is that if the template type does not provide the "type", then compiler gives error in below code. I suspect I need to use SFINAE here, but haven't been able to figure out a suitable approach for it, even after puzzling and browsing related questions for a good part of the afternoon.
How to define the EventType template so that it works as intended? I want to keep the EventType<T> syntax.
#include <iostream>
struct One {
//This type is ignored, and double is used, because UseOverride = true is not specified:
using type = short;
};
struct Two {
static constexpr bool UseOverride = true;
using type = int;
};
struct Three {
static constexpr bool UseOverride = false;
//I don't want the compiler to complain that "type" is not available here (because it should default to double anyhow since
//the class instructs not to use the override). But compile does generate error.
//How to avoid this?
};
template <typename T, typename = void>
struct overrideInfoProvided : std::false_type {};
template <typename T>
struct overrideInfoProvided<T, decltype((void)T::UseOverride, void())> : std::true_type {};
template <typename T>
constexpr bool Override()
{
if constexpr (overrideInfoProvided<T>::value)
{
return T::UseOverride;
}
return false;
}
template<class T>
using EventType = typename std::conditional_t<Override<T>(), typename T::type, double>;
template <class T>
struct Test
{
typename EventType<T> member;
Test()
{
std::cout << member << std::endl;
}
};
int main()
{
Test<One>();
Test<Two>();
//Gives error:
//Test<Three>();// `type': is not a member of any direct or indirect base class of `three';
}
I don't want the compiler to complain that "type" is not available here (because it should default to double anyhow since the class instructs not to use the override). But compiler does generate error. How to avoid this?
Just defer the access to ::type with the below type_identity helper:
template <typename T>
struct type_identity { using type = T; };
template <typename T>
using EventType = typename std::conditional_t<Override<T>()
, T
, type_identity<double>>::type;
// ~~~~~~~~~~~~^
DEMO
You are on the right track, but you don't need to have separate checks for the existence of useOverride, and type. Instead, you can do both of the checks in the same sfinae class:
template <typename T, typename = void, typename = void>
struct EventType_T {
using t = double; // default if useOverride or type doesn't exist
};
template <typename T>
struct EventType_T<T, std::void_t<decltype(T::UseOverride)>,
std::void_t<typename T::type>> {
// choose type if useOverride is true, and double otherwise
using t = std::conditional_t<T::UseOverride, typename T::type, double>;
};
template <typename T>
using EventType = typename EventType_T<T>::t;
Here's a demo. This allows you to still use the EventType<T> syntax as before.
Note, the t member instead of type is unconventional, but since we are already testing for a type member in T, this might make it clearer what's going on. I would recommend using type once yo understand how the solution works.
I have an issue I'm facing where I'm trying to build a factory function that,
given an ID and a type will return the correct (templated) subclass.
What this is trying to solve:
The id() values are sent across a network as soon as a connection is established, and specify to the receiver how a sequence of bytes are encoded. The receiver knows in advance the type T that it expects, but does not know how that type T is encoded on the wire until it gets this value. It also specifies how return values (of some type U, where U may or may not be the same type as T) should be marshalled when they are returned. This code is used generally, i.e. there are multiple senders/receivers that use/expect different types; the types used between a given sender/receiver pair are always fixed, however.
A basic sketch of the problem: we have a (simplified) base class that defines id()
template <typename T>
class foo
{
public:
virtual ~foo() { }
// Other methods
// This must return the same value for every type T
virtual std::uint8_t id() const noexcept = 0;
};
From there, we have some subclasses:
template <typename T>
class bar : public foo<T>
{
public:
std::uint8_t id() const noexcept override { return 1; }
};
template <typename T>
class quux : public foo<T>
{
public:
std::uint8_t id() const noexcept override { return 2; }
};
For the actual factory function, I need to store something that
erases the type (e.g. bar, quux) so that I can store the actual
creation function in a homogenous container.
Effectively, I want semantics that are roughly equivalent to:
struct creation_holder
{
// Obviously this cannot work, as we cannot have virtual template functions
template <typename T>
virtual foo<T>* build() const;
};
template <template <typename> class F>
struct create : public creation_holder
{
// As above
template <typename T>
foo<T>* build() const override
{
return new F<T>();
}
};
std::unordered_map<std::uint8_t, create*>& mapping()
{
static std::unordered_map<std::uint8_t, create*> m;
return m;
}
template <typename T, template <typename> class F>
bool register_foo(F<T> foo_subclass,
typename std::enable_if<std::is_base_of<foo<T>, F<T>>::value>::type* = 0)
{
auto& m = mapping();
const auto id = foo_subclass.id();
creation_holder* hold = new create<F>();
// insert into map if it's not already present
}
template <typename T>
foo<T>* from_id(std::uint8_t id)
{
const auto& m = mapping();
auto it = m.find(id);
if(it == m.end()) { return nullptr; }
auto c = it->second;
return c->build<T>();
}
I've played around with a number of ideas to try and get something with similar
semantics, but with no luck. Is there a way to do this (I don't care if the
implementation is significantly different).
Some utility types for passing around types and bundles of types:
template<class...Ts>
struct types_t {};
template<class...Ts>
constexpr types_t<Ts...> types{}; // C++14. In C++11, replace types<T> with types_t<T>{}. Then again, I don't use it.
template<class T>
struct tag_t {};
template<class T>
constexpr tag_t<T> tag{}; // C++14. In C++11, replace tag<T> with tag_t<T>{} below
Now we write a poly ifactory.
Here is an ifactory:
template<template<class...>class Z, class T>
struct ifactory {
virtual std::unique_ptr<Z<T>> tagged_build(tag_t<T>) const = 0;
virtual ~ifactory() {}
};
you pass in the tag you want to build and you get out an object. Pretty simple.
We then bundle them up (this would be easier in c++171, but you asked for c++11):
template<template<class...>class Z, class Types>
struct poly_ifactory_impl;
The one type case:
template<template<class...>class Z, class T>
struct poly_ifactory_impl<Z,types_t<T>>:
ifactory<Z, T>
{
using ifactory<Z, T>::tagged_build;
};
the 2+ case:
template<template<class...>class Z, class T0, class T1, class...Ts>
struct poly_ifactory_impl<Z,types_t<T0, T1, Ts...>>:
ifactory<Z, T0>,
poly_ifactory_impl<Z, types_t<T1, Ts...>>
{
using ifactory<Z, T0>::tagged_build;
using poly_ifactory_impl<Z, types_t<T1, Ts...>>::tagged_build;
};
We import the tagged_build method down into the derived classes. This means that the most-derived poly_ifactory_impl has all of the tagged_build methods in the same overload set. We'll use this to dispatch to them.
Then we wrap it up pretty:
template<template<class...>class Z, class Types>
struct poly_ifactory:
poly_ifactory_impl<Z, Types>
{
template<class T>
std::unique_ptr<Z<T>> build() const {
return this->tagged_build(tag<T>);
}
};
notice I'm returning a unique_ptr; returing a raw T* from a factory method is code smell.
Someone with a poly_ifactory<?> just does a ->build<T>() and ignores the tagged_ overloads (unless they want them; I leave them exposed). Each tagged_build is virtual, but build<T> is not. This is how we emulate a virtual template function.
This handles the interface. At the other end we don't want to have to implement each build(tag_t<T>) manually. We can solve this with the CRTP.
template<class D, class Base, template<class...>class Z, class T>
struct factory_impl : Base {
virtual std::unique_ptr<Z<T>> tagged_build( tag_t<T> ) const override final {
return static_cast<D const*>(this)->build_impl( tag<T> );
}
using Base::build;
};
template<class D, class Base, template<class...>class Z, class Types>
struct poly_factory_impl;
the 1 type case:
template<class D, class Base, template<class...>class Z, class T0>
struct poly_factory_impl<D, Base, Z, types_t<T0>> :
factory_impl<D, Base, Z, T0>
{
using factory_impl<D, Base, Z, T0>::tagged_build;
};
the 2+ type case:
template<class D, class Base, template<class...>class Z, class T0, class T1, class...Ts>
struct poly_factory_impl<D, Base, Z, types_t<T0, T1, Ts...>> :
factory_impl<D, poly_factory_impl<D, Base, Z, types_t<T1, Ts...>>, Z, T0>
{
using factory_impl<D, poly_factory_impl<D, Base, Z, types_t<T1, Ts...>>, Z, T0>::tagged_build;
};
what this does is write a series of tagged_build(tag_t<T>) overloads of the ifactory methods, and redirects them to D::build_impl(tag_t<T>), where D is a theoretical derived type.
The fancy "pass Base around" exists to avoid having to use virtual inheritance. We inherit linearly, each step implementing one tagged_build(tag<T>) overload. All of them dispatch downward non-virtually using CRTP.
Use looks like:
struct bar {};
using my_types = types_t<int, double, bar>;
template<class T>
using vec = std::vector<T>;
using my_ifactory = poly_ifactory< vec, my_types >;
struct my_factory :
poly_factory_impl< my_factory, my_ifactory, vec, my_types >
{
template<class T>
std::unique_ptr< vec<T> > build_impl( tag_t<T> ) const {
return std::make_unique< std::vector<T> >( sizeof(T) );
// above is C++14; in C++11, use:
// return std::unique_ptr<vec<T>>( new vec<T>(sizeof(T)) );
}
};
and an instance of my_factory satisfies the my_ifactory interface.
In this case, we create a unique ptr to a vector of T with a number of elements equal to sizeof(T). It is just a toy.
Live example.
The pseudo code design.
The interface has a
template<class T> R build
function. It dispatches to
virtual R tagged_build(tag_t<T>) = 0;
methods.
The Ts in question are extracted from a types_t<Ts...> list. Only those types are supported.
On the implementation side, we create a linear inheritance of CRTP helpers. Each inherits from the last, and overrides a virtual R tagged_build(tag_t<T>).
The implementation of tagged_build uses CRTP to cast the this pointer to a more-derived class and call build_impl(tag<T>) on it. This is an example of non-runtime polymorphism.
So calls go build<T> to virtual tagged_build(tag_t<T>) to build_impl(tag<T>). Users just interact with one template; implementors just implement one template. The glue in the middle -- the virtual tagged_build -- is generated from a types_t list of types.
This is about 100 lines of "glue" or helper code, and in exchange we get effectively virtual template methods.
1 in c++17 this becomes:
template<template<class...>class Z, class...Ts>
struct poly_ifactory_impl<Z,types_t<Ts...>>:
ifactory<Z, Ts>...
{
using ifactory<Z, Ts>::tagged_build...;
};
which is much simpler and clearer.
Finally, you can do something vaguely like this without a central list of types. If you know both the caller and the callee know the type you could pass a typeid or typeindex into the ifactory, pass a void* or something similar out over the virtual dispatch mechanism, and cast/check for null/do a lookup in a map to types.
The internal implementation would look similar to this one, but you wouldn't have to publish types_t as part of your formal (or binary) interface.
Externally, you would have to "just know" what types are supported. At runtime, you might get a null smart (or dumb, ick) pointer out if you pass in an unsupported type.
With a bit of care you could even do both. Expose an efficient, safe mechanism to get compile-time known types applied to a template. Also expose a "try" based interface that both uses the efficient compile-time known system (if the type matches) and falls back on the inefficient runtime checked on. You might do this for esoteric backwards binary compatibility reasons (so new software can connect over an obsolete interface to new or old API implementations and handle having an old API implementation dynamically).
But at that point, have you considered using COM?
I'm developing a simple event driven application in C++11 based on the publish/subscribe pattern. Classes have one or more onWhateverEvent() method invoked by the event loop (inversion of control). Since the application is in fact a firmware, where code size is critical and flexibility is not of high priority, the 'subscribe' part is a simple table with event id's and associated handlers.
Here's a very simplified code of the idea:
#include <functional>
enum Events {
EV_TIMER_TICK,
EV_BUTTON_PRESSED
};
struct Button {
void onTick(int event) { /* publish EV_BUTTON_PRESSED */ }
};
struct Menu {
void onButtonPressed(int event) { /* publish EV_SOMETHING_ELSE */ }
};
Button button1;
Button button2;
Menu mainMenu;
std::pair<int, std::function<void(int)>> dispatchTable[] = {
{EV_TIMER_TICK, std::bind(&Button::onTick, &button1, std::placeholders::_1) },
{EV_TIMER_TICK, std::bind(&Button::onTick, &button2, std::placeholders::_1) },
{EV_BUTTON_PRESSED, std::bind(&Menu::onButtonPressed, &mainMenu, std::placeholders::_1) }
};
int main(void)
{
while(1) {
int event = EV_TIMER_TICK; // msgQueue.getEventBlocking();
for (auto& a : dispatchTable) {
if (event == a.first)
a.second(event);
}
}
}
This compiles and runs fine with a desktop compiler, and std:function<void(int)>> fn = std::bind(&SomeClass::onSomething), &someInstance, std::placeholders::_1) elegantly implements type erasure so the event dispatch table can hold handlers of different classes, thus different types.
The problem comes with the embedded compiler (AVR-GCC 4.8.3) which supports C++11, but there's no Standard C++ Library: no <functional> header. I was thinking how can I re-create the above behavior with compiler features only. I evaluated a few options, but there are objections for each (by the compiler or me):
Create an interface with a virtual void Handler::onEvent(int event) method, and derive Button and Menu from it. The dispatch table can hold interface pointers, and virtual method calls do the rest. This is the most simple approach but I don't like the idea of limiting the number of event handler methods to one per class (with doing local if-else event dispatch), and having the overhead of a virtual method call per event.
My second idea still contains a virtual method call, but has no restrictions on the Button and Menu class. It's a virtual method call based type-erasure with functors:
struct FunctBase {
virtual void operator()(int event) = 0;
};
template<typename T>
struct Funct : public FunctBase
{
T* pobj; //instance ptr
void (T::*pmfn)(int); //mem fun ptr
Funct(T* pobj_, void (T::*pmfn_)(int)) : pobj(pobj_), pmfn(pmfn_) {}
void operator()(int ev) override {
(pobj->*pmfn)(ev);
}
};
Funct can hold instance and method pointers, and the dispatch table can be constructed of FunctBase pointers. This way table is as flexible as with function/bind: can hold any class (type) and any number of handlers per class. My only problem that it still contains 1 virtual method call per event, it's just moved to the functor.
My third idea is a simple hack converting method pointers to function pointers:
typedef void (*Pfn)(void*, int);
Pfn pfn1 = reinterpret_cast<Pfn>(&Button::onTick);
Pfn pfn2 = reinterpret_cast<Pfn>(&Menu::onButtonPressed);
As far as I know this is Undefined Behavior and indeed makes the compiler emit a big fat warning. It's based on the assumption that c++ methods have an implicit 1st argument pointing to this. Nonetheless it works, it's lightweight (no virtual calls), and it's flexible.
So my question: Is it possible to do something like option 3 in clean C++ way? I know there's a void* based type-erasure technique (opposed to virtual method call in option 2), but I don't know how to implement it. Looking at desktop version with std::bind also gives me the impression that it binds the first implicit argument to be the instance pointer, but maybe that's just the syntax.
A solid, efficient, std::function<R(Args...)> replacement isn't hard to write.
As we are embedded, we want to avoid allocating memory. So I'd write a small_task< Signature, size_t sz, size_t algn >. It creates a buffer of size sz and alignment algn in which it stores its erased objects.
It also stores a mover, a destroyer, and an invoker function pointer. These pointers can either be locally within the small_task (maximal locality), or within a manual struct vtable { /*...*/ } const* table.
template<class Sig, size_t sz, size_t algn>
struct small_task;
template<class R, class...Args, size_t sz, size_t algn>
struct small_task<R(Args...), sz, algn>{
struct vtable_t {
void(*mover)(void* src, void* dest);
void(*destroyer)(void*);
R(*invoke)(void const* t, Args&&...args);
template<class T>
static vtable_t const* get() {
static const vtable_t table = {
[](void* src, void*dest) {
new(dest) T(std::move(*static_cast<T*>(src)));
},
[](void* t){ static_cast<T*>(t)->~T(); },
[](void const* t, Args&&...args)->R {
return (*static_cast<T const*>(t))(std::forward<Args>(args)...);
}
};
return &table;
}
};
vtable_t const* table = nullptr;
std::aligned_storage_t<sz, algn> data;
template<class F,
class dF=std::decay_t<F>,
// don't use this ctor on own type:
std::enable_if_t<!std::is_same<dF, small_task>{}>* = nullptr,
// use this ctor only if the call is legal:
std::enable_if_t<std::is_convertible<
std::result_of_t<dF const&(Args...)>, R
>{}>* = nullptr
>
small_task( F&& f ):
table( vtable_t::template get<dF>() )
{
// a higher quality small_task would handle null function pointers
// and other "nullable" callables, and construct as a null small_task
static_assert( sizeof(dF) <= sz, "object too large" );
static_assert( alignof(dF) <= algn, "object too aligned" );
new(&data) dF(std::forward<F>(f));
}
// I find this overload to be useful, as it forces some
// functions to resolve their overloads nicely:
// small_task( R(*)(Args...) )
~small_task() {
if (table)
table->destroyer(&data);
}
small_task(small_task&& o):
table(o.table)
{
if (table)
table->mover(&o.data, &data);
}
small_task(){}
small_task& operator=(small_task&& o){
// this is a bit rude and not very exception safe
// you can do better:
this->~small_task();
new(this) small_task( std::move(o) );
return *this;
}
explicit operator bool()const{return table;}
R operator()(Args...args)const{
return table->invoke(&data, std::forward<Args>(args)...);
}
};
template<class Sig>
using task = small_task<Sig, sizeof(void*)*4, alignof(void*) >;
live example.
Another thing missing is a high quality void(Args...) that doesn't care if the passed-in callable has a return value.
The above task supports move, but not copy. Adding copy means that everything stored must be copyable, and requires another function in the vtable (with an implementation similar to move, except src is const and no std::move).
A small amount of C++14 was used, namely the enable_if_t and decay_t aliases and similar. They can be easily written in C++11, or replaced with typename std::enable_if<?>::type.
bind is best replaced with lambdas, honestly. I don't use it even on non-embedded systems.
Another improvement would be to teach it how to deal with small_tasks that are smaller/less aligned by storing their vtable pointer rather than copying it into the data buffer, and wrapping it in another vtable. That would encourage using small_tasks that are just barely large enough for your problem set.
Converting member functions to function pointers is not only undefined behavior, often the calling convention of a function is different than a member function. In particular, this is passed in a particular register under some calling conventions.
Such differences can be subtle, and can crop up when you change unrelated code, or the compiler version changes, or whatever else. So I'd avoid that unless you have little other choice.
As noted, the platform lacks libraries. Every use of std above is tiny, so I'll just write them:
template<class T>struct tag{using type=T;};
template<class Tag>using type_t=typename Tag::type;
using size_t=decltype(sizeof(int));
move
template<class T>
T&& move(T&t){return static_cast<T&&>(t);}
forward
template<class T>
struct remove_reference:tag<T>{};
template<class T>
struct remove_reference<T&>:tag<T>{};
template<class T>using remove_reference_t=type_t<remove_reference<T>>;
template<class T>
T&& forward( remove_reference_t<T>& t ) {
return static_cast<T&&>(t);
}
template<class T>
T&& forward( remove_reference_t<T>&& t ) {
return static_cast<T&&>(t);
}
decay
template<class T>
struct remove_const:tag<T>{};
template<class T>
struct remove_const<T const>:tag<T>{};
template<class T>
struct remove_volatile:tag<T>{};
template<class T>
struct remove_volatile<T volatile>:tag<T>{};
template<class T>
struct remove_cv:remove_const<type_t<remove_volatile<T>>>{};
template<class T>
struct decay3:remove_cv<T>{};
template<class R, class...Args>
struct decay3<R(Args...)>:tag<R(*)(Args...)>{};
template<class T>
struct decay2:decay3<T>{};
template<class T, size_t N>
struct decay2<T[N]>:tag<T*>{};
template<class T>
struct decay:decay2<remove_reference_t<T>>{};
template<class T>
using decay_t=type_t<decay<T>>;
is_convertible
template<class T>
T declval(); // no implementation
template<class T, T t>
struct integral_constant{
static constexpr T value=t;
constexpr integral_constant() {};
constexpr operator T()const{ return value; }
constexpr T operator()()const{ return value; }
};
template<bool b>
using bool_t=integral_constant<bool, b>;
using true_type=bool_t<true>;
using false_type=bool_t<false>;
template<class...>struct voider:tag<void>{};
template<class...Ts>using void_t=type_t<voider<Ts...>>;
namespace details {
template<template<class...>class Z, class, class...Ts>
struct can_apply:false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z, void, Ts...>;
namespace details {
template<class From, class To>
using try_convert = decltype( To{declval<From>()} );
}
template<class From, class To>
struct is_convertible : can_apply< details::try_convert, From, To > {};
template<>
struct is_convertible<void,void>:true_type{};
enable_if
template<bool, class=void>
struct enable_if {};
template<class T>
struct enable_if<true, T>:tag<T>{};
template<bool b, class T=void>
using enable_if_t=type_t<enable_if<b,T>>;
result_of
namespace details {
template<class F, class...Args>
using invoke_t = decltype( declval<F>()(declval<Args>()...) );
template<class Sig,class=void>
struct result_of {};
template<class F, class...Args>
struct result_of<F(Args...), void_t< invoke_t<F, Args...> > >:
tag< invoke_t<F, Args...> >
{};
}
template<class Sig>
using result_of = details::result_of<Sig>;
template<class Sig>
using result_of_t=type_t<result_of<Sig>>;
aligned_storage
template<size_t size, size_t align>
struct alignas(align) aligned_storage_t {
char buff[size];
};
is_same
template<class A, class B>
struct is_same:false_type{};
template<class A>
struct is_same<A,A>:true_type{};
live example, about a dozen lines per std library template I needed.
I would put this "std library reimplementation" into namespace notstd to make it clear what is going on.
If you can, use a linker that folds identical functions together, like the gold linker. template metaprogramming can cause binary bloat without a solid linker to strip it.
Your 1st idea is your typical object oriented solution to the problem. It's perfectly fine, but a bit heavy-handed - not quite as usable as std::function. Your 3rd idea is undefined behavior. Nope nope nope.
Your 2nd idea - now there's something we can work with! This is close to how std::function is actually implemented. We can write a class that can take any object that is callable with int and returns void:
class IntFunc {
private:
struct placeholder {
virtual ~placeholder() = default;
virtual void call(int ) = 0;
};
template <typename F>
struct holder : placeholder {
holder(F f) : func(f) { }
void call(int i) override { func(i); }
F func;
};
// if you wrote your own unique_ptr, use it here
// otherwise, will have to add rule of 5 stuff
placeholder* p;
public:
template <typename F>
IntFunc(F f)
: placeholder(new holder<F>(f))
{ }
template <typename Cls>
IntFunc(Cls* instance, void (Cls::*method)(int )) {
auto lambda = [=](int i){ (instance->*method)(i); };
placeholder = new holder<decltype(lambda)>(lambda);
}
void operator()(int i) {
p->call(i);
}
};
With that, you basically have std::function<void(int)> in a usable, generic way.
Now a 4th idea might be to just extend your 3rd idea to something usable. Actually use function pointers:
using Pfn = void (*)(void*, int);
And then use lambdas to make such things:
Pfn buttonOnTick = [](void* ctxt, int i){
static_cast<Button*>(ctxt)->onTick(i);
};
But then you have to hold on to the contexts somehow - which adds extra work.
Before I try to write all the STL stuff by hand, I try to use the STL which I already have from the compiler itself. Because most of the STL code you use is header only, I simply include it and do some minor hacks to get them compiled. In fact id did 10 minutes to get it ready to link!
I used avr-gcc-5.2.0 version without any problems for the task. I have no old installation and I believe it is easier to install the actual version in some minutes instead of fixing problems from the old one.
After compile your example code for avr I got link errors:
build-check-std-a520-nomemdbg-os-dynamic-noncov/main.o: In function `std::__throw_bad_function_call()':
/home/krud/own_components/avr_stl/avr_stl009/testing/main.cpp:42: undefined reference to `operator delete(void*, unsigned int)'
/home/krud/own_components/avr_stl/avr_stl009/testing/main.cpp:42: undefined reference to `operator delete(void*, unsigned int)'
collect2: error: ld returned 1 exit status
Simply write your own __throw_bad_function_call and get rid of the link problem.
For me it makes really no sense to write a own STL implementation. Here I simply used the headers which comes from the compiler installation ( gcc 5.2.0).
First of all, some context
As part of a policy-based particle engine I'm currently writting, I have done some type-erasure on policy classes. Specifically, I have done type erasure on the particle evoution policies:
A particle evolution policy is just a policy which says how the data (Coordinates, speed, color, etc) of a particle changes along the simulation. This is its interface:
struct evolution_policy
{
template<PARTICLE_DATA>
void operator()( PARTICLE_DATA& data );
void step();
};
The operator() overload just takes a particle data and modifies it acording to the supposed policy. The step() function is just a function to update (Advance) the state of the policy (If the policy has some state).
Among other cases, I just needed type erasure to allow the user to use simple function entities (Functions, lambdas, etc) to be used as a evolution policy, for example:
add_policy( []( some_particle_data_type& data ) { /* do something with */ } );
Where the add_policy() function takes some policy and stores it in a vector. As you can see, the point of type erasure is to treat different kinds of policy classes/entities in the same homogeneous way.
The problem:
I'm using the dynamic dispatch approach for type erasure:
template<tyoename PARTICLE_DATA>
struct type_erased_policy
{
public:
void operator()( PARTICLE_DATA& data )
{
(*_policy)( data );
}
void step()
{
_policy->step();
}
private:
struct policy_interface
{
virtual ~policy_interface() {}
virtual void operator()( PARTICLE_DATA& data ) = 0;
virtual void step() = 0;
};
template<typename POLICY>
class policy_impl : public policy_interface
{
public:
void operator()( PARTICLE_DATA& data ) override
{
_policy( particle );
}
void step() override
{
_policy.step();
}
private:
POLICY _policy;
};
std::shared_ptr<policy_interface> _policy;
};
With that in mind, its easy to write an specialization to type-erase shared pointers of policies, for example:
template<typename T>
class policy_impl<std::shared_ptr<T>> : public policy_interface
{
public:
void operator()( PARTICLE_DATA& data ) override
{
(*_policy)( data );
}
void step( cpp::evolution_policy_step step_type ) override
{
_policy->step( step_type );
}
private:
std::shared_ptr<T> _policy;
};
That could be useful if we need to share a policy between particles, for example.
We could write an specialization for std::function<void(PARTICLE_DATA&)> policies using that pattern. However, this only works for explicit instantations of std::function<void(PARTICLE_DATA&)>, i.e. if we pass a lambda function to the type_erased_policy ctor, it will instantiate the generic policy_impl case, because there is no specialization for the lambda type.
As lambda functors (closures) are unique (In other words, the type of a lambda expression is unique and unespecified) there is no easy way to do this kind of type erasure over a lambda.
My question is: My goal is to take any function entity (A lambda, a functor, a function pointer, a std::function) and do type erasure on it in the way explained above. Is there any (other) way to match lambdas and/or other function entities to do type-erasure on them?
Platform:
I'm using GCC 4.8.2
First, a policy class that detects .step():
namespace impl{
// eat a type and do nothing with it:
template<typename T> struct type_sink { typedef void type; };
template<typename T> using TypeSink = typename type_sink<T>::type;
// detect .step on T (T& means rvalue, T means lvalue, and T const& means const lvalue, etc)
template<typename T, typename=void>
struct has_step:std::false_type {};
template<typename T>
struct has_step<T, TypeSink< decltype( std::declval<T>().step() ) > >:
std::true_type
{};
}
template<typename T> struct has_step : impl::has_step<T> {};
So now we have a has_step<T> traits class that is true_type if T has a .step() method callable, and false_type otherwise.
If we are feeding this to a function, we can pick which implementation to run with tag dispatching:
template<typename T>
return_type_whatever type_erase_helper( T&& t, std::true_type /* test passed */ ) {
// branch 1
}
template<typename T>
return_type_whatever type_erase_helper( T&& t, std::false_type /* test failed */ ) {
// branch 2
}
template<typename T>
return_type_whatever type_erase( T&& t ) {
return type_erase_helper( std::forward<T>(t), has_step< typename std::decay<T>::type& >() );
}
If you really want to specialize a particular class based on having step or not, you can use SFINAE techniques. But type erasure does not rely on the type erasure implementation being based off of specialization: I'd just use tag dispatching on the function that generates the type erasure implementation object.
We can daisy-chain such tag dispatching. Another good one might be is_signature_compatible< T, R(Args...) >:
namespace impl {
template<typename T, typename Sig,typename=void>
struct is_signature_compatible:std::false_type {};
template<typename T, typename R, typename... Args>
struct is_signature_compatible< T, R(Args...), typename std::enable_if<
std::is_convertible< typename std::result_of< T(Args...) >::type, R >::value
>::type >:std::true_type {};
// dunno if this is needed? Possibly, and shouldn't hurt:
template<typename T, typename... Args>
struct is_signature_compatible< T, void(Args...),
TypeSink< typename std::result_of< T(Args...) >::type >
>:std::true_type {};
}
template<typename T, typename Sig>
struct is_signature_compatible:impl::is_signature_compatible<T,Sig> {};
which we can then use to split the wheat from the chaff in a less "error occurs 10 recursive template invocations deep" way.
To facilitate the technique wrap your lambda function in a std::function. Since its constructor is greedy, it will absorbe any callable, yet the gain of wrapping would be declaring an explicit type
auto f1 = [](double a, double b)->int {
return a + b > 5.; // example function body
});
std::function<int(double,double)> f2 ( [](double a, double b)->int {
return a + b > 5.; // example function body
};);
So in the above context f1 faces the problems you mention, while f2 is a lambda (preserves all the convinience in declaring and using it) that, in a sense, has no 'stray type'
I am having trouble getting my code to compile. clang, g++ and icpc all give different error messages,
A bit of background before getting to the question itself:
I am working now on a template class hierarchy for working with Matrices. There are template parameters for the data type (either float or double) and for "Implementation Policy" -- at present this includes regular C++ code with loops and Intel MKL versions. The following is an abridged summary (please disregard lack of forward references, etc. in this -- that is unrelated to my question):
// Matrix.h
template <typename Type, typename IP>
class Matrix : public Matrix_Base<Type, IP>;
template <typename Matrix_Type>
class Matrix_Base{
/* ... */
// Matrix / Scalar addition
template <typename T>
Matrix_Base& operator+=(const T value_) {
return Implementation<IP>::Plus_Equal(
static_cast<Matrix_Type&>(*this), value_);
/* More operators and rest of code... */
};
struct CPP;
struct MKL;
template <typename IP>
struct Implementation{
/* This struct contains static methods that do the actual operations */
The trouble that I'm having right now is related to the implementation of the Implementation class (no pun intended). I know that I can use specialization of the Implementation template class to specialize template <> struct Implementation<MKL>{/* ... */}; however, this will result in a lot of code duplication as there are a number of operators (such as matrix-scalar addition, subtraction, ... ) for which both the generic and the specialized versions use the same code.
So, instead, I thought that I could get rid of the template specialization and just use enable_if to provide different implementations for those operators which have different implementations when using MKL (or CUDA, etc.).
This has proven to me to be more challenging than I had originally expected. The first -- for operator += (T value_) works fine. I added in a check just to make sure that the parameter is reasonable (this can be eliminated if it is the source of my troubles, which I doubt).
template <class Matrix_Type, typename Type, typename enable_if<
std::is_arithmetic<Type>::value >::type* dummy = nullptr>
static Matrix_Type& Plus_Equal(Matrix_Type& matrix_, Type value_){
uint64_t total_elements = matrix_.actual_dims.first * matrix_.actual_dims.second;
//y := A + b
#pragma parallel
for (uint64_t i = 0; i < total_elements; ++i)
matrix_.Data[i] += value_;
return matrix_;
}
However, I am having a really hard time figuring out how to deal with operator *=(T value_). This is due to the fact that float and double have different implementations for MKL but not in the general case.
Here is the declaration. Note that the 3rd parameter is a dummy parameter and was my attempt at forcing function overloading, since I cannot use partial template function specialization:
template <class Matrix_Type, typename U, typename Type =
typename internal::Type_Traits< Matrix_Type>::type, typename enable_if<
std::is_arithmetic<Type>::value >::type* dummy = nullptr>
static Matrix_Type& Times_Equal(Matrix_Type& matrix_, U value_, Type dummy_ = 0.0);
Definition for general case. :
template<class IP>
template <class Matrix_Type, typename U, typename Type, typename enable_if<
std::is_arithmetic<Type>::value >::type* dummy>
Matrix_Type& Implementation<IP>::Times_Equal(Matrix_Type& matrix_, U value_, Type){
uint64_t total_elements = matrix_.actual_dims.first * matrix_.actual_dims.second;
//y := A - b
#pragma parallel
for (uint64_t i = 0; i < total_elements; ++i)
matrix_.Data[i] *= value_;
return matrix_;
}
The trouble starts when I try to implement a specialization for MKL:
template<>
template <class Matrix_Type, typename U, typename Type, typename enable_if<
std::is_arithmetic<Type>::value >::type* dummy>
Matrix_Type& Implementation<implementation::MKL>::Times_Equal(
Matrix_Type& matrix_,
U value_,
typename enable_if<std::is_same<Type,float>::value,Type>::type)
{
float value = value_;
MKL_INT total_elements = matrix_.actual_dims.first * matrix_.actual_dims.second;
MKL_INT const_one = 1;
//y := a * b
sscal(&total_elements, &value, matrix_.Data, &const_one);
return matrix_;
}
This gives me an error in clang:
_error: out-of-line definition of 'Times_Equal' does not match any declaration in 'Implementation'_
and in g++ (shortened somewhat)
_error: template-id `Times_Equal<>' for 'Matrix_Type& Implementation::Times_Equal(...)' does not match any template declaration.
The code compiles perfectly fine if I change the 3rd parameter to be Type, rather than having the enable_if. But when I do that, I cannot see how to have separate implementations for float and double.
Any help would be greatly appreciated.
I think this would be very tedious to implement using std::enable_if, as the general cases would have to be implemented with an enable_if that turned it on if it doesn't fit one of the specializations.
Specifically addressing your code, I don't think the compiler is able to deduce Type in your MKL specialization as it is hidden away in the std::enable_if, and thus this specialization would never get called.
Instead of using enable_if you could perhaps do something like this:
#include<iostream>
struct CPP {};
struct MKL {};
namespace Implementation
{
//
// general Plus_Equal
//
template<class Type, class IP>
struct Plus_Equal
{
template<class Matrix_Type>
static Matrix_Type& apply(Matrix_Type& matrix_, Type value_)
{
std::cout << " Matrix Plus Equal General Implementation " << std::endl;
// ... do general Plus_Equal ...
return matrix_;
}
};
//
// specialized Plus_Equal for MKL with Type double
//
template<>
struct Plus_Equal<double,MKL>
{
template<class Matrix_Type>
static Matrix_Type& apply(Matrix_Type& matrix_, double value_)
{
std::cout << " Matrix Plus Equal MKL double Implementation " << std::endl;
// ... do MKL/double specialized Plus_Equal ...
return matrix_;
}
};
} // namespace Implementation
template <typename Type, typename IP, typename Matrix_Type>
class Matrix_Base
{
public:
// ... matrix base implementation ...
// Matrix / Scalar addition
template <typename T>
Matrix_Base& operator+=(const T value_)
{
return Implementation::Plus_Equal<Type,IP>::apply(static_cast<Matrix_Type&>(*this), value_);
}
// ...More operators and rest of code...
};
template <typename Type, typename IP>
class Matrix : public Matrix_Base<Type, IP, Matrix<Type,IP> >
{
// ... Matrix implementation ...
};
int main()
{
Matrix<float ,MKL> f_mkl_mat;
Matrix<double,MKL> d_mkl_mat;
f_mkl_mat+=2.0; // will use general plus equal
d_mkl_mat+=2.0; // will use specialized MKL/double version
return 0;
}
Here I used class specialization instead of std::enable_if. I found that you were very inconsistent with the IP, Type, and Matrix_Type types in your examples, so I hope I use them correctly here.
As an aside in relation to the comments on std::enable_if. I would use the form
template<... , typename std::enable_if< some bool >::type* = nullptr> void func(...);
over
template<... , typename = std::enable_if< some bool >::type> void func(...);
as it enables you to do some function overloads you couldn't do with the other form.
Hope you can use it :)
EDIT 20/12-13: After re-reading my post i found that I should explicitly do CRTP (Curiously Recurring Template Pattern), which i added in the above code. I pass both Type and IP to Matrix_Base. If you find this tedious, one could instead provide a matrix traits class, from which Matrix_Base could take them out.
template<class A>
struct Matrix_Traits;
// Specialization for Matrix class
template<class Type, class IP>
struct Matrix_Traits<Matrix<Type,IP> >
{
using type = Type;
using ip = IP;
};
Then Matrix_Basewould now only take one template argument, namely the matrix class itself, and get the types from the traits class
template<class Matrix_Type>
class Matrix_Base
{
// Matrix / Scalar addition
template <typename T>
Matrix_Base& operator+=(const T value_)
{
// We now get Type and IP from Matrix_Traits
return Implementation::Plus_Equal<typename Matrix_Traits<Matrix_Type>::type
, typename Matrix_Traits<Matrix_Type>::ip
>::apply(static_cast<Matrix_Type&>(*this), value_);
}
};