Using array of arguments to call a function via pointer - c++

I am writing my own reflection library and this is the scenario I am facing:
Base class Method providing the interface for querying stuff about methods and calling them (hence the variadic template method)
class Method : public INamedEntity
{
public:
...
template<typename... TArgs>
void Call(void* instance, TArgs&&... args) const
{
AnyType arguments[] = { args... };
size_t nArguments = sizeof...(TArgs);
_Call(instance, arguments, nArguments);
}
void Call(void* instance) const;
protected:
// This was supposed to be the link to the derived class
virtual void _Call(void* instance, AnyType arguments[], size_t count) const = 0;
};
The meat and all the implementation is in derived class which is templated (TMethod) and uses the types passed in to deduce stuff like argument types, correct member pointer signature etc.
template<typename TReturn, typename TClass, class... Args>
class TMethod<TReturn(TClass, Args...)> : public Method
{
typedef TReturn(TClass::*MethodPointer)(Args...);
public:
TMethod(MethodPointer method)
, m_pointer(method)
{}
...
protected:
void _Call(void* instance, AnyType arguments[], size_t count) const
{
/// ???
(((TClass*)instance)->*m_pointer)( _How to even call this_ );
}
private:
MethodPointer m_pointer;
const Type* m_clazz;
const Type* m_return;
HashedString m_name;
};
Obviously the above code is not what I aim after and honestly I have no clue how to find a workaround for this problem. Of course I am not insisting on expanding the parameter pack into array and passing it like this, as I would really like any working method at the moment. How would you approach passing the arguments from the base class Call function and route it in some usable fashion to the derived implementation?
I am open to any suggestions but I am aware of the possibility of creating a big if statements and making overloads with 'n' number of parameters in the derived class but this seems to be the least elegant solution I come up with till now.
Also I anyone has a better title for this question please let me know ;)

Related

C++ static member function vs lambda overhead

I have some kind of templated base class
template<typename Derived>
class Base { };
and want to store derived instances of it in a list.
For that I use a using derived_handle = std::unique_ptr<void, void(*)(void*) alias.
When I now add a derived instance to the list i cound use a static member function as deleter
class foo {
template<typename Derived, typename... Args>
void add_base(Args&&... args) {
auto derived = derived_handle{new Base{std::forward<Args>(args)..., &foo::_deleter<Derived>};
_derived.emplace_back(std::move(derived));
}
private:
template<typename Baser>
void _deleter(void* base) {
delete static_cast<Base*>(base);
}
std::vector<derived_handle> _derived{};
};
or a lambda
class foo {
template<typename Derived, typename... Args>
void add_base(Args&&... args) {
auto deleter = [](auto* derived){
delete static_cast<Derived*>(derived);
}
auto derived = derived_handle{new Base{std::forward<Args>(args)..., std::move(deleter)};
_derived.emplace_back(std::move(derived));
}
private:
std::vector<derived_handle> _derived{};
};
Are there any advantages/disadvantages of the lambda version I should be aware of?
Time for a frame challenge!
You've made some bad decisions in that code. Most people who use unique_ptr, even in a polymorphic context, don't need custom deleters at all. The only reason you do, is because of your type erasure, and that's only there because Base<A> and Base<B> are unrelated types.
If you really need Base<T>, have it inherit from an actual polymorphic (and non-templated) base class with a virtual destructor. Then you don't need unique_ptr<void> (a really bad code smell), and you can actually use your list in a type-safe manner.

Template specialization enable_if

I am trying to specialize a template this way:
class PropertyBase
{
public:
SfPropertyBase(string name)
{
Name = name;
}
virtual ~SfPropertyBase() {}
string Name;
virtual bool FromString(Object* obj, string str) = 0;
};
template< typename T>
class Property : public SfPropertyBase
{
public:
Property(string name) : SfPropertyBase(name)
{
//specific to Property stuff
}
template<typename U = T>
typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
template<typename U = T>
typename std::enable_if<!std::is_class<U>::value || !std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
}
Then, when I try to initialize an instance of this class:
auto prop = new Property<int>("IntProperty");
I get invalid new-expression of abstract class type Property<int>. I understand that there is an abstract function in PropertyBase, but I also provide both specializations for Property, where T is a class and where it isn't.
What is going on and how to fix it?
Note: what I want to achieve is to specialize FromString if T is a class/pointer and all the other cases.
Both the FromString in Property are function template, they can't override the non-template virtual function of the base class. (In fact functions templates cannot be virtual functions).
You could add another non-template FromString in Property; and you can ensure the overriding by using the keyword orverride. e.g.
bool FromString(Object* obj, string str) override {
return FromString<>(obj, str);
}
LIVE
A function template cannot be used as an overrider for a non-template virtual function. A function template is not a function, it's a recipe for creating functions on demand when a call is made.
Code will have to call FromString on your derived class object directly for SFINAE to work. If you want to provide a different overrider based on the template parameter type, one approach is to go via an intermediate base.
template<typename T, typename = void>
struct FromStringProvider;
template<typename T>
struct FromStringProvider<T, typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value)>::type> : SfPropertyBase {
bool FromString(Object* obj, string str) override
{
//do something
return true;
}
};
If you need access to the deriving class, then a CRTP based approach can be used. Just pass the deriving class as an extra parameter and rely on its static interface to access the parts you need.
This alternative approach is especially useful if you have sets of virtual functions, all under the same conditions.

template class to class with template member

A class template like this
template <typename... T>
class Action {
private:
std::tuple<T...> m_args;
public:
Action(T... args) : m_args(args...) {}
}
to a class with template member. The reason why doing this is want to make only one type of class, so that object with different args still belong to the same class for easy manipulation.
class Action {
private:
// this does not work, how to declare the tuple type so that It can hold any arguments list.
template <typename... T>
std::tuple<T...> m_args;
public:
template <typename... T>
Action(T... args) : m_args(args...) {}
}
Put your mind in the perspective of the compiler. How would our trusty friend know how much storage is required for Action, if that size would be dependent upon what constructor was resolved? This is not possible.
template<typename... T>
Action(T... args) : m_args(args...) {}
// wait what???
Action(int someArg) : m_args(someArg) {}
Let's say the second constructor was valid, or we had two Action objects with different arguments passed into the constructor -- what should be sizeof(Action)?
If you get stuck on an issue like this, think as the compiler: there was probably some person who had to give a good enough reason why it shouldn't be supported, simply because it only complicates the implementation and also has performance implications.
Since you mentioned using a pointer instead of an aggregated object, I figured I'd show you how to do this for completeness. Do note that this has performance implications, because you are now allocating the memory for m_args on the heap, rather than the stack.
class Action
{
public:
template<typename... T>
using TArgs = std::tuple<T...>;
std::shared_ptr<void> m_args;
template<typename... T>
Action(T... args)
: m_args(std::make_shared<TArgs<T...>>(args...)) {}
};
Action myAction(1, 2.0, 3.5f);
auto *myActionArgs =
static_cast<Action::TArgs<int, double, float>*>(myAction.m_args.get());
// 2.0
double secondArg = std::get<1>(*myActionArgs);
This does not look like fun to maintain.

c++ force method to be defined even though it is not inherited

So I have run into a problem in which I need a method to be defined for any types that inherit from a base class that I have created, yet I need that method to be static, is there anyway I can force it to be created?
The reason I need this I will have people be extending my base class, but I need to be able to guarantee a call to a function like so derivedType derivedType::createFromSerialized(std::string) will work to create a new instance from a serialization.
Edit: I am trying to follow Richard J. Ross III's advice and use static_assert however I am running into some problems with that and I have a feeling its due to it being called from a templated class but I can't figure out how to fix it.
template <typename indType> class population {
static_assert(std::is_function<indType::createFromSerialized>::value, "message");
....
};
However that is giving me an error of to refer to a type member of a template parameter, use ‘typename indType:: createFromSerialized’ and no type named 'createFromSerialized' in 'class test'
The reason I am trying to use static_assert is to get a nicer error message that will give information about the proper function signature for createFromSerialized instead of just one that says its not defined.
This can be done by combining static_assert and SFINAE detection technique.
template<typename T, typename V = bool>
struct has_deserialize : std::false_type { };
template<typename T>
struct has_deserialize<T,
typename std::enable_if<
std::is_same<decltype(&T::createFromSerialized),
T* (*)(const std::string&)>::value,
bool
>::type
> : std::true_type { };
template <typename T>
class test
{
static_assert(has_deserialize<T>::value, "No suitable createFromSerialized");
};
What you are trying to accomplish is possible through a factory pattern very easily. Not sure whether you can accomplish it using templates.
Here's a skeleton of how I would go about implementing the serialization functionality.
SerializationFunctor.h
class Base;
class SerializationFunctor
{
virtual Base* operator(FILE* in) const = 0;
};
Base.h
class Base
{
bool registerSerializationFunction(std::string const& identifier,
SerializationFunctor* functor);
};
ConcreteA.h
class ConcreteA
{
};
ASerializationFunctor.cc
class ASerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteA and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteA", new ASerializationFunctor());
ConcreteB.h
class ConcreteB
{
};
BSerializationFunctor.cc
class BSerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteB and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteB", new BSerializationFunctor());

C++: "specializing" a member function template to work for derived classes from a certain base class

I have a base class MessageBase, from which I derive various other message classes, e.g., MessageDerived. I have another class that does some processing on various types of data, including a catchall method template:
struct Process {
void f(int a);
void f(const char* b);
template<typename T> void f(const T &t) { ... }
};
So if I call Process::f on a message object, the template method is called.
Now I want to add custom functionality for for my message classes. I am not allowed to change Process, so I want to derive from it (but even if I could change it, I can't find a way to get the custom functionality). I tried:
struct ProcessDerived : public Process {
void f(const MesaageBase& m) { ... } // Custom functionality for messages.
};
But that only works when I call ProcessDerived::f on a MessageBase object. If I invoke it on a MessageDerived object, the template method gets selected instead.
Is there a way to get the custom function selected on all message classes while letting the template catch all other types?
You need to use SFINAE here. Here is an example (note that it needs c++11 to work):
struct ProcessDerived : public Process
{
template<typename T> void f(const T &t, typename std::conditional<std::is_base_of<MessageBase, T>::value, int, void>::type = 0)
{
/// do something specific
}
template<typename T> void f(const T &t, ...)
{
return Process::f (t);
}
};
};
You can read more about it at http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
ProcessDerived::f shadows all definitions of Process::f (see here: Overloading rules for inheritance in C++). So calling ProcessDerived::f with a MessageDerived object calls ProcessDerived::f(const MessageBase&) as this is the only visible f, but e.g.
ProcessDerived pd;
pd(42);
won't compile. You need to add a
using Process::f;
in ProcessDerived for the problem you described showing up. The solution proposed by Alex Telishev while I was writing fixes both problems at once, however.