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.
Related
I'm sure there's a name for what I'm looking for, I just don't know it (and if I did, I'd probably find the answer already). Basically, I want to implement my own lightweight version of std::function for sports. I want to initialize it with a lambda, and later invoke it. I can wrap the lambda with my template wrapper class, nothing to it:
struct CInvokableAbstract {
virtual ~CInvokableAbstract() = default;
};
template <class InvokableObject>
struct CInvokableBasic : public CInvokableAbstract
{
CInvokableBasic(InvokableObject&& target) : _invokable(std::move(target)) {}
template <typename... Args>
typename std::result_of<decltype(&InvokableObject::operator())(Args...)>::type operator()(Args... args) const
{
return _invokable(std::forward<Args>(args)...);
}
private:
InvokableObject _invokable;
};
Now I can make my class that's semantically similar to std::function, but how can I store the exact type of the lambda in order to convert the type-erased object back to its original concrete type?
struct CInvokableDeferred
{
template <class InvokableObject>
CInvokableDeferred(InvokableObject&& target) noexcept : _invokable(std::make_unique<CInvokableBasic<InvokableObject>>(std::move(target))) {}
template <typename... Args>
void operator()(Args... args) const
{
// How can I know the original concrete type to cast this to?
static_cast<???>(_invokable.get())->(std::forward<Args>(args)...);
}
private:
std::unique_ptr<CInvokableAbstract> _invokable;
};
I can't think of any template trickery that could do that, yet we know it's possible (unless std::function uses some compiler built-ins, or otherwise is implemented internally in the compiler rather than being normal C++ code).
Note that I'm using a compiler that doesn't have full C++17 support, so I can't use e. g. auto-deduced return type.
You need to rewrite your base class as follows:
template <typename Ret, typename... Args>
class CInvokableAbstract {
virtual ~CInvokableAbstract() = default;
virtual Ret operator()(Args... args) = 0;
};
This will make your base class dependent on the signature (which it has to be in order to be usable) and provide the actual interface for the invocable object.
Note that this part of code actually has nothing to do with type-erase, it's just plain old dynamic polymorphism. It's the combination of static (CInvokableBasic template) and dynamic (CInvokableAbstract interface) polymorphisms that make type-erasure possible.
Not sure if this question has been asked before. I am implementing a factory class. Every instance should inherit from a base class InstBase and should be initialized through a centralized factory.
class InstBase {
friend class Factory;
private:
InstBase() = default;
factory* factory;
}
class Factory {
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
return new Derived(std::forward<ArgsT>(args)...)
}
}
class MyInst : public InstBase {
public:
MyInst(int a, int b) {...};
}
factory.get<MyInst>(1, 2);
As you can see in this example, the interface takes a Derived as a template and initialize an instance with user-defined argument list passed to the constructor of Derived. However, what I want to add here is assigning the pointer to the factory in which the instance is created. This can be done by:
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
auto ptr = new Derived(std::forward<ArgsT>(args)...);
ptr->factory = this;
return ptr;
}
I felt this is a bit redundant because the base class InstBase is always created before the derived and can be only newed by the factory class. Is there any trick to achieve this goal without changing the interface of get? It doesn't make sense for me to ask user to attach another pointer to factory in the argument list (e.g., factory.get<MyInst>(1, 2, &factory)).
If you want to forbid the use of Factory as a type for the arguments, you can use something like this (C++11 compliant):
template<typename>
constexpr bool isBaseOf() { return false; }
template<typename T, typename U, typename... O>
constexpr bool isBaseOf() { return std::is_base_of<T, typename std::decay<U>::type>::value || isBaseOf<T, O...>(); }
Thus changing the factory method as it follows:
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
static_assert(not isBaseOf<Factory, ArgsT...>(), "!");
return new Derived(std::forward<ArgsT>(args)...)
}
That said, I don't like it too much, for I won't use a class that does not let me use the parameters I want!!
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());
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 ;)
Consider some function:
template<typename F>
void foo(F f) {
std::unique_ptr<int> p = f();
// do some stuff with p
}
Because unique_ptr decrees a default template argument, default_delete, for D, any function object passed to foo that returns a unique_ptr with a non-default deleter fails to compile. For example,
int x = 3;
foo([&x](){
// use empty deleter
return std::unique_ptr<int>(&x, [](int*){});
});
However, I could see this being potentially useful, and I don't see a direct reason why it shouldn't be possible. Is there a common approach for addressing this?
Edit
The easy fix would be to define foo instead to use the following:
std::unique_ptr<int, std::function<void(int*)>> p = f();
But I'm wondering why this couldn't have been incorporated into the interface for unique_ptr? Is there a reason the class interface couldn't provide this generic attribute? Are there approaches for "wrapping" this kind of thing into a new definition?
For example,
template<typename T>
using Generic_unique_ptr =
std::unique_ptr<
T,
std::function< void(typename std::unique_ptr<T>::element_type*) >
>;
But this seems dangerous because it exposes the potential to do something like the follwing,
Generic_unique_ptr<int> p(new int());
which would leave the deleter uninitialized and exhibit undefined behavior. Perhaps some way to provide an instance of std::default_delete<T> as the default deleter?
If all you want to do is use the pointer in a function, you can just
use the auto keyword; the compiler will deduce the type of unique_ptr
which has been used and thus automatically do the right thing:
template <typename F>
void foo(F f)
{
auto p = f();
p->bar();
}
Now, from your comment, we know that this is not all you want, but you
want to be able to store the unique_ptr in your class to work with
it later. This creates a set of completely different problems:
unique_ptr<T, D1> and unique_ptr<T, D2> are different types. Thus we need to know what unique_ptr<T, D> will be returned by your functor F
Even if we knew the return type of F in advance, our class can still only store unique_ptr<T, D1> and not unique_ptr<T, D2>.
The easiest way around this (that I can think of, there might be better
ways) is type erasure.
We create ourselves a base class that exposes the pointer managed by the
unique_ptr:
template <typename T>
struct wrapper
{
virtual ~wrapper() {}
virtual T const * get() const = 0;
virtual T * get() = 0;
};
From that class inherits our actual storage class, which deduces the type
of unique_ptr:
template <typename T, typename F>
struct storage
: wrapper<T>
{
storage(F f) { p_ = f(); }
T const * get() const { return p_.get(); }
T * get() { return p_.get(); }
private:
typename std::result_of<F()>::type p_;
};
In the class you actually care about, you can now store a pointer to our
base class and use polymorphism to access the underlying object, in this
case the unique_ptr. Assume we moved the classes above into
namespace detail to hide them from the user:
template <typename T>
class some_class
{
public:
template <typename F>
void store(F f)
{
storage_.reset(new detail::storage<T, F>(f));
}
T const * get() const { return storage_->get(); }
T * get() { return storage_->get(); }
private:
std::unique_ptr<detail::wrapper<T>> storage_;
};
You can find a fully working example here.
But I'm wondering why this couldn't have been incorporated into the interface for unique_ptr?
Because to do so would force all of std::function's overhead onto everyone. unique_ptr is intended to be useful for pretty much any case of single ownership of a pointer. You pay for what you use; not everyone who uses a custom deleter needs that deleter to be generic. This way, they don't have to pay for it.
Also, the current methodology allows it to handle non-pointer resources, as the deleter can specify exactly what type gets stored in the unique_ptr.
If you want to provide this generic deleter construct, you could create a class that (privately) inherits from unique_ptr and replicates its interface, minus the constructor that doesn't take a deleter instance. That way, the user is forced to pass a deleter function in.