Understanding UB and pointer-arithmetic - c++

I have a generic reference-counted heap-allocated wrapper class. So my class is basically just a pointer:
template <typename T>
class Refcounted {
struct model {
std::atomic<std::size_t> count{1};
T value;
};
model* m_self;
public:
...
Refcounted(const Refcounted& other) : m_self(other.m_self) {
assert(m_self);
++m_self->count;
}
...
T& operator*() { return m_model->value; }
};
Now, I'd like to be able to get a T& even in a context where T is forward-declared. As I understand it, I can't, because if T is just forward-declared, it can't know the layout of model (in particular, it can't know the offset of value because it can't know T's alignment).
I believe that if I swapped the order of model, it would be well-defined behavior to reinterpret_cast, correct?:
template <typename T>
class Refcounted {
struct model {
T value;
std::atomic<std::size_t> count{1};
};
model* m_self;
public:
Refcounted(T&& x) : m_self(new model(std::move(x))) {
static_assert(offsetof(model, value) == 0, "Using this assumption below to reinterpret_cast");
}
...
Refcounted(const Refcounted& other) : m_self(other.m_self) {
assert(m_self);
++m_self->count;
}
...
T& operator*() { return *reinterpret_cast<T*>(m_model); }
};
Assuming that's correct, great... but now the copy-constructor requires T to be defined because it needs to find m_self->count. I had a thought for dealing with that, but I suspect it's UB: If I set up the model struct so that std::atomic<std::size_t> count is first and there's no padding between it and the T, then Refcounted keeps a void* pointer to the value field, as in m_valptr{&(new model(std::move(x)))->value}, then I could reinterpret_cast<T*>(m_valptr) to get at the value (which I think (?) is still well-defined-behavior). Is there any defined way to go from that pointer to a pointer to count? In principal, it's just decrementing the pointer by std::atomic<std::size_t>, but I suspect it breaks rules that I don't fully understand about what can and cannot be done with pointers.
I could add a second pointer to Refcounted or I could make model use a virtual interface, but that adds overhead. I feel like this should be possible but that there are spooky language rules getting in the way.

Related

C++20 Concept for checking presence of private class members

Consider the situation of having some class A together with a factory class Factory. A is supposed to have only private constructors (to prevent the user from creating such an object), and is friends with Factory, who can then construct Objects of type A.
A also has some private attribute which cannot be set in in A's constructor (because the value is not known yet), but will be computed by Factory and then set correctly before A is returned.
Now i have the situation that I have similar classes B,C, ... to A that should also be constructed by Factory, which will thus be a template.
So the situation is currently
template<typename T>
class Factory {
public:
T get() {
T t;
void* computed_value = nullptr; // suppose we compute a
t._value = computed_value;
return t;
}
};
class A {
// Some public methods for the user
friend class Factory<A>;
private:
A() : _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// some more attributes that will correctly be initialsed by the default constructor
};
class B {
//Some public methods for the user
friend class Factory<B>;
private:
B(): _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// Some more attributes that will correctly be initialised by the default constructor
};
void foo() {
Factory<A> a_factory;
A a_elem = a_factory.get();
Factory<B> b_factory;
B b_elem = b_factory.get();
}
Actually, an instance of Factory<A> also stores some values that are used in the construction of some A, that are set by the constructor of Factory, this is why i use instances of the Factory and not static methods.
Now comes the point: I would like to use Concepts in order to constrain the template<typename T> that is used by the Factory, so something like:
template<typename T>
concept Factorable = requires (T t) {
std::same_as<void*, decltype(t._value)>;
};
template<Factorable t>
class Factory { //...
As expected, this does not work, because the corresponding required expressions are private and thus not available, Factorable<A> will just be false.
Now, hanging the attribute and constructor of class A to public will thus lead to a nice generic Factory and the below (correct) code
template<Factorable T>
class Factory {
public:
T get() {
T t;
void* computed_value = nullptr; // suppose we compute a
t._value = computed_value;
return t;
}
};
class A {
// Some public methods for the user
template<Factorable T>
friend class Factory;
public:
A() : _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// some more attributes that will correctly be initialsed by the default constructor
};
class B {
//Some public methods for the user
template<Factorable T>
friend class Factory;
public:
B(): _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// Some more attributes that will correctly be initialised by the default constructor
};
void use() {
Factory<A> a_factory;
A a_elem = a_factory.get();
Factory<B> b_factory;
B b_elem = b_factory.get();
}
Note the subtlety that we now had to declare all generic variants of Factory as a friend of classes A and B, since Factory<A> cannot be evaluated while defining class A itself and thus not explicitly declared as a friend. I am however fine with this, since in the implementation of the Factory<T> we will not access other classes than T anyways (It would however be nice to achieve a friend class Factory<A>, but this is not my priority).
But this approach leads to the massive problem that a user can now generate instances of A by just calling its constructor, which just sets _value = nullptr, so we get 'invalid' instances of A that may lead to undefined behaviour etc. So this is really not the way to go for, although the use of the concepts in above expression would be nice.
So my question now is:
How can I achieve both of the above, in order have private constructors and attributes, but still use concepts
I found out that concepts are actually context-sensitive, in the sense that the required expressions are checked in the invoking context, so in fact the following code will correctly compile
template<typename T>
concept Factorable = requires (T t) {
std::same_as<void*, decltype(t._value)>;
};
template<typename T>
class Factory {
static_assert(Factorable<T>);
public:
T get() {
T t;
void* computed_value = nullptr; // suppose we compute a
t._value = computed_value;
return t;
}
};
class A {
// Some public methods for the user
template<typename T>
friend class Factory;
private:
A() : _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// some more attributes that will correctly be initialsed by the default constructor
};
class B {
//Some public methods for the user
template<typename T>
friend class Factory;
private:
B(): _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// Some more attributes that will correctly be initialised by the default constructor
};
void use() {
Factory<A> a_factory;
A a_elem = a_factory.get();
Factory<B> b_factory;
B b_elem = b_factory.get();
}
since now the compiler will first accept any typename T as generic and then check the concept for the given T within the context of the class, which will thus evaluate to true, since Factory is friends with both A and thus has access to its data members.
So this approach can actually guarantee user-safe instantiation of class A and throwing corresponding errors when the static_assertion fails to evaluate, but of course this is not the way a concept is intended to use, since then we basically just fall back to duck-typing as it was before the introduction of concepts and manually assert certain things, which loses the desired properties of concepts (late error throwing etc., but also losing IDE completion).
A solution would of course be to have the possibility to require the presence of private attributes in a concept, something like the following
//Suppose the existence of a function like std::ignore_private(expression)
template<typename T>
concept Factorable = requires (T t) {
std::same_as<void*, decltype(std::ignore_private(t._value))>;
}
where std::ignore_private is of course completely made up (and i also don't know what syntax it actually should have), but you get the point what i actually want.
So, is there any way to express something like this in a concept?
At least, i could imagine that, since checking for private attributes is a constexpr and can also be checked at compile time.
If you don't find a better solution a compromise could be to constrain the method:
template<typename T>
class Factory {
public:
T get() requires Factorable<T>
{
// ...
}
};
After experimenting around a while, i came up with the following workaround, using an additional Tester class, that has to be declared friend by A:
template<typename T>
concept PrivateFactorable = requires (T t) {
std::same_as<void*, decltype(t._value)>;
};
template<typename T> class Tester {
public:
constexpr static bool factorable = PrivateFactorable<T>;
};
template<typename T>
concept Factorable = Tester<T>::factorable;
template<Factorable T>
class Factory {
public:
T get() {
T t;
void* computed_value = nullptr; // suppose we compute a meaningful value here
t._value = computed_value;
return t;
}
};
class A {
// Some public methods for the user
template<Factorable T>
friend class Factory;
friend class Tester<A>;
public:
A() : _value(nullptr) {} //initialised with nullptr since we have no meaningful value (yet)
void* _value;
// some more attributes that will correctly be initialsed by the default constructor
};
This will correctly redirect Factorable<A> into the tester class, who can evaluate the concept withing friend context with A. The only downside is that A has to have yet another friend (and we get some more concepts in the background), but this seems okay
First, I think it’s a compiler bug if the value of a concept depends on the lexical location of requesting it.
It could interfere with subsumption where that matters, but you can write the constraint directly:
template<class T> requires std::same_as<void*, decltype(T::_value)>
class Factory {…};
Substitution failures in a constraint cause it to be unsatisfied whether it’s in a concept or not.

C++11 Pure virtual 'templated' return type in non-templated base class

Here's what I'm trying to accomplish:
I'm trying to created a linked list of various types. In order to accomplish this, I figured polymorphism would be a great way to go about.
I have two classes, AttributeBase and Attribute. AttributeBase is used by AttributeSet, which just stores the start and end points of the linked list of Attribute<T>'s (as AttributeBase*'s) and does modification on the list. AttributeBase is a base class of Attribute<T> that is only in the design for the sake of making generic pointers. Attribute<T>, of course, is the specific type of AttributeBase where the actual value is stored. The main data of each Attribute<T> is an inherited string (the attribute's name, or 'key' if you will) and a value of type T.
So, thus far I have (simplified):
class AttributeBase
{
public:
AttributeBase() = delete;
AttributeBase* GetNext() { return next; };
AttributeBase* GetPrev() { return prev; };
std::string GetName() { return name; };
//Sometimes I need to get/set the value stored in a derived class
//But, how would I define the function here since the return
//type is of type T as defined in Attribute?
virtual ???? GetValue = 0;
virtual void SetValue(????) = 0;
friend class AttributeSet;
private:
AttributeBase* next = nullptr;
AttributeBase* prev = nullptr;
std::string name;
};
template <class T>
class Attribute : public AttributeBase
{
public:
Attribute( std::string _name, T _value ){ name = _name; value = _value };
T GetValue(){ return value; };
void Setvalue(T){ value = T; };
private:
T value;
};
class AttributeSet
{
public:
template <class T>
void Add(std::string,T); //Add an Attribute<T>(std::string,T) to the list
void Delete(std::string);
bool Contains(std::string _name); //Scan the list to determine if an
//attribute with name of _name exists
template <class T>
T Get(std::string); //Scan the list for 'name' and return
//AttributeBase*->GetValue()
private:
AttributeBase* start = nullptr;
AttributeBase* end = nullptr;
}
Since I tried to keep AttributeBase generic and non-templated (to avoid strongly-typed start and end pointers in AttributeSet), this brings up a problem. How do I specify an as-of-yet unspecified return type for the virtual function BaseAttribute::GetValue(). I first tried using auto, got a compile error.
Being as no instances of AttributeBase are ever actually created (and the default constructor deleted) I figured it would be possible to leave out GetValue and define it in the derived class. However, if I try *AttributeBase->GetValue() it errors out since GetValue() isn't defined in AttributeBase, only the subclasses. You would think the compiler would know that the pointer has to point to a derived class (the only derived type) since AttributeBase cannot be directly constructed.
So, in order to use GetValue() I have to know the type of the previous value ahead of time to be able to cast the AttributeBase* to an Attribute*. This would be trivial if AttributeBase itself were templated and contained a value T type. I could then just access AttributeBase*->type to determine the type of pointer I need to cast. However, like I said, templating AttributeBase destroys the intended use of the object.
More than likely, I'm going about this in a completely wrong way (yet again). But at this point I am stuck for ideas. Any help would be appreciated!
So a truly general solution doesn't exist. You just can't get any arbitrary type from a base class because all your overrides of your base class virtual function have to have the same return type.
That leaves you two options.
First, you can decide in advance that you're going to have your list hold any object that derives from some common base type. This will severely limit what you can put into your list, but at least you have full freedom with those objects once they're there.
Second, depending on what you want to actually do with the objects once they're in your list, you can look at the new Boost.TypeErasure library. If all you need to do with list is, say, output them all, or some either small amount of operations, this can help you get there.
Since the signatures of GetValue and SetValue depend on a type, they need to be templates. But they can be template members without requiring a class template.
class AttributeBase
{
public:
template <typename T> T GetValue() const;
template <typename T> void SetValue(T);
//...
};
template <typename T>
T AttributeBase::GetValue() const
{
return dynamic_cast<Attribute<T>&>(*this).GetValue();
}
template <typename T>
void AttributeBase::SetValue(T val)
{
dynamic_cast<Attribute<T>&>(*this).SetValue(val);
}
template <typename T>
T AttributeSet::Get(std::string const& name) const
{
// (assuming a private helper method Find().)
const AttributeBase* attr = Find(name);
if ( !attr )
throw std::invalid_argument("attribute not in set");
return attr->GetValue<T>();
}
One gotcha, though: these functions will all throw an exception if you happen to use the wrong type. And SetValue might automatically deduce its template argument, and might do so incorrectly. For example, if a is a AttributeBase& reference which is really an Attribute<long int>, then a.SetValue(1) is the same as a.SetValue<int>(1), which will throw. The correct expression would be a.SetValue<long int>(1) (or a.SetValue(1L), but I'd prefer the explicit template argument).

Is such a downcast safe?

Suppose we have the following code:
#include <memory>
#include <vector>
struct BaseComponent
{
template <typename T>
T * as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
int main()
{
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new PositionComponent);
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
return 0;
}
In the T * as() method, should I use a static_cast or a dynamic_cast? are there times when the the conversion will fail? Do I need to dynamic_cast like this instead?
auto *ptr = dynamic_cast<T*>(this);
if(ptr == nullptr)
throw std::runtime_error("D'oh!");
return ptr;
In your case there is no way to tell statically whether this is the right type or not.
What you may want is a CRTP (Curiously recurring template pattern):
template <class T>
struct BaseComponent
{
T* as()
{
return static_cast<T*>(this);
}
virtual ~BaseComponent() {}
};
template <typename T>
struct Component : public BaseComponent<T>
{
virtual ~Component() {}
};
struct PositionComponent : public Component<PositionComponent>
{
float x, y, z;
virtual ~PositionComponent() {}
};
This way you can do:
auto x = yourBaseComponent.as();
and have the right child type statically.
The code that you present is correct and well formed, but the cast in general is not safe. If the actual object was not a PositionComponent, then the compiler would very gladly assume that it is and you would be causing undefined behavior.
If you replace the cast with dynamic_cast, then the compiler will generate code that at runtime verifies that the conversion is valid.
The real question is why would you need this. There are reasons, but more often than not the use of casts are an indication of issues with your design. Reconsider whether you can do better (i.e. redesign your code so that you don't need to go explicitly converting types)
Since you are using unique_ptr<BaseComponent>, naturally there could be times when the conversion fails: the insertion of new data in the vector and consumption of that data are done in unrelated places, and in such a way that the compiler cannot enforce it.
Here is an example of an invalid cast:
struct AnotherComponent : public Component<AnotherComponent>
{
virtual ~AnotherComponent () {}
};
std::vector<std::unique_ptr<BaseComponent>> mComponents;
mComponents.emplace_back(new AnotherComponent);
// !!! This code compiles, but it is fundamentally broken !!!
auto *pos = mComponents[0]->as<PositionComponent>();
pos->x = 1337;
In this respect, using dynamic_cast would provide better protection against incorrect usage of the as<T> function. Note that the incorrect usage may not be intentional: any time the compiler cannot check the type for you, and you have a potential type mismatch, you should prefer dynamic_cast<T>
Here is a small demo to illustrate how dynamic_cast would offer you a degree of protection.
You should always use dynamic_cast when casting polymorphic objects that are derived from a baseclass.
In a case where mComponents[0] is not PositionComponent (or a class derived therefrom), the above code would fail. Since the whole purpose of having mComponents hold a pointer to BaseComponent is so that you can put other things than PositionComponent objects into the vector, I'd say you need to care for that particular scenario.
In general, it's a "bad smell" when you are using dynamic_cast (or generally casting objects that are derived from a common baseclass). Typically it means the objects should not be held in a common container, because they are not closely enough related.

Interfaces and covariance problem

I have a particular class that stores a piece of data, which implements an interface:
template<typename T>
class MyContainer : public Container<T> {
class Something : public IInterface {
public:
// implement *, ->, and ++ here but how?
private:
T x;
};
// implement begin and end here, but how?
private:
Something* data; // data holds the array of Somethings so that references to them can be returned from begin() and end() to items in this array so the interface will work, but this makes the problem described below
};
And I have an array of Somethings.
I have the need for Something to implement an interface class (IInterface in the example) which:
Contains pure virtual member functions which return something such that *retval returns a reference to the x member, retval-> returns the address of x, and ++retval makes retval refer to the next Something in the array.
The things that the pure virtual members return can be inherited from and returned by the implementation of the members
container[i] (where container is the array holding the Something objects) always returns something such that *retval always returns a reference to the same T for the same i.
Right now, the interface looks like this:
template<typename T>
class Container {
class IInterface {
public:
virtual T& operator*() = 0;
virtual T* operator->() = 0;
virtual IInterface& operator++(); // this is the problem
};
// returning a reference right now to support covariance, so subclasses can
// derive from Container and then have a member class derive from IInterface
// and override these to return their derived class, but this has a problem
virtual IInterface& begin() = 0;
virtual IInterface& end() = 0;
};
My current solution (have the virtual methods return an IInterface& and return a Something& in the implementation) has no problem with the requirements, except for the ++retval requirement. Because the Something is directly tied to the object it holds and can't point to a T with a pointer, there's no way that I can find to get ++ to make the variable refer to the next Something in the array.
If it helps to know, this is an iterator type system. I would have made it with the STL style iterators (where you just have an array of T) that are passed around by value and hold pointers to the values they represent, but that would break the interface because only references and pointers are covariant, and the objects already have to exist somewhere else already (in my code they're in the array) so you don't return a reference to a local object.
The purpose of this setup is so that one can write functions that take a Container& and iterate the container without knowing what type of container it is:
void iterate(Container<int>& somecontainer) {
Container<int>::IIterator i = somecontainer.begin(); // right now this would return a reference, but it doesn't/can't work that way
while (i != somecontainer.end()) {
doSomething(*i);
++i; // this is the problem
}
}
It's kind of difficult for me to describe, don't hesitate to let me know if you need more information.
What you are trying to do is called type erasure. Basically you want to provide a value type (which is the same across the whole inheritance hierarchy) that wraps the particular iterator type and offers a uniform dynamic interface.
Type erasure is usually implemented with a non-virtual class (the type erased) that stores a pointer to a virtual base class that implements the erasure, from which you derive different types that wrap each particular iterator. The static class would offer templated constructor/assignment operators that would dynamically instantiate an object of the derived type and store the pointer internally. Then you only need to implement the set of operations as dispatch to the internal object.
For the simplest form of type erasure possible, you can take a look at the implementation of boost::any (documentation is here)
Sketch:
namespace detail {
template<typename T>
struct any_iterator_base {
virtual T* operator->() = 0; // Correct implementation of operator-> is tough!
virtual T& operator*() = 0;
virtual any_iterator_base& operator++() = 0;
};
template <typename T, typename Iterator>
class any_iterator_impl : any_iterator_base {
Iterator it;
public:
any_iterator_impl( Iterator it ) : it(it) {}
virtual T& operator*() {
return *it;
}
any_iterator_impl& operator++() {
++it;
return *this;
}
};
}
template <typename T>
class any_iterator {
detail::any_iterator_base<T>* it;
public:
template <typename Iterator>
any_iterator( Iterator it ) : it( new detail::any_iterator_impl<T,Iterator>(it) ) {}
~any_iterator() {
delete it;
}
// implement other constructors, including copy construction
// implement assignment!!! (Rule of the Three)
T& operator*() {
return *it; // virtual dispatch
}
};
The actual implementation becomes really messy. You need to provide different versions of the iterator for the different iterator types in the standard, and the detail of the implementation of the operators might not be trivial either. In particular operator-> is applied iteratively until a raw pointer is obtained, and you want to make sure that your type erased behavior does not break that invariant or document how you break it (i.e. limitations on the type T that your adaptor can wrap)
For extended reading:
- On the Tension Between Object-Oriented and Generic Programming in C++
- any_iterator: Implementing Erasure for C++ iterators
- adobe any_iterator ,
I would suggest a look at the Visitor pattern.
Other than that, what you want is a value type that will be imbued with polymorphic behavior. There is a much simpler solution than James' using your IInterface.
class IInterface
{
virtual ~IInterface() {}
virtual void next() = 0;
virtual void previous() = 0;
virtual T* pointer() const = 0;
virtual std::unique_ptr<IInterface> clone() const = 0;
};
std::unique_ptr<IInterface> clone(std::unique_ptr<IInterface> const& rhs) {
if (!rhs) { return std::unique_ptr<IInterface>(); }
return rhs->clone();
}
class Iterator
{
friend class Container;
public:
Iterator(): _impl() {}
// Implement deep copy
Iterator(Iterator const& rhs): _impl(clone(rhs._impl)) {}
Iterator& operator=(Iterator rhs) { swap(*this, rhs); return *this; }
friend void swap(Iterator& lhs, Iterator& rhs) {
swap(lhs._impl, rhs._impl);
}
Iterator& operator++() { assert(_impl); _impl->next(); return *this; }
Iterator& operator--() { assert(_impl); _impl->previous(); return *this; }
Iterator operator++(int); // usual
Iterator operator--(int); // usual
T* operator->() const { assert(_impl); return _impl->pointer(); }
T& operator*() const { assert(_impl); return *_impl->pointer(); }
private:
Iterator(std::unique_ptr<IInterface> impl): _impl(impl) {}
std::unique_ptr<IInterface> _impl;
};
And finally, the Container class will propose:
protected:
virtual std::unique_ptr<IInterface> make_begin() = 0;
virtual std::unique_ptr<IInterface> make_end() = 0;
And implement:
public:
Iterator begin() { return Iterator(make_begin()); }
Iteraotr end() { return Iterator(make_end()); }
Note:
You can do away with the std::unique_ptr if you can avoid the ownership issue. If you can restrict the IInterface to be behavioral only (by extracting the state into Iterator), then you can have the Strategy pattern kick-in, and use a pointer a statically allocated object. This way, you avoid dynamic allocation of memory.
Of course, it means your iterators won't be so rich, as it requires IInterface implementations to be stateless, and implementing "filtering" iterators, for example, would become impossible.
Have you thought about using CRTP. I find it a good candidate here. Here is a brief demo. It just explains your ++retval problem (if I understood it correctly). You have to change your IInterface definition from pure virtual to CRTP type interface.
template<class Derived>
struct IInterface
{
Derived& operator ++ ()
{
return ++ *(static_cast<Derived*>(this));
}
};
struct Something : public IInterface<Something>
{
int x;
Something& operator ++ ()
{
++x;
return *this;
}
};
There are some limitations of CRTP, that the template will always follow your IInterface. Which means that if you are passing a Something object to a function like this:
foo(new Something);
Then, foo() should be defined as:
template<typename T>
void foo(IInterface<T> *p)
{
//...
++(*p);
}
However for your problem, it can be a good fit.
Like you said, the problem is that instances of Something are tied to the object it holds. So let's try to untie them.
The key point to remember is that in OOP, public non-const data members are generally frowned upon. In your current implementation, every Something instance is tied to having a data member T x which is publicly accessible. Instead of this, is considered better to make an abstraction of this, i.e. provide accessor methods instead:
class Something : IInterface
{
private:
T x;
public:
T GetX()
{
return x;
}
};
Now the user has know idea what type of thing x is, much less that x exists.
This is a good first step, however, since you wish be able to have x refer to different objects at different times, we're pretty much going to have to make x be a pointer. And as a concession to conventional code, we'll also make GetX() return a const reference, rather than a regular value:
class Something: IInterface
{
private:
T *x;
public:
T const& GetX()
{
return *x;
}
};
It's now trivial to implement the methods in IInterface:
class Something: IInterface
{
private:
T *x;
public:
T const& GetX()
{
return *x;
}
T& operator*()
{
return *x;
}
T* operator->()
{
return x;
}
Something& operator++()
{
++x;
return *this;
}
};
The ++ operator is trivial now - it really just applies the ++ to x.
The user now has no idea that a pointer was used. All they know is that their code works right. That's the most important point in OOP's principle of data abstraction.
Edit
As far as implementing the begin and end methods of Container, that shouldn't be too difficult either, but it will require some changes to Container.
First off, let's add a private constructor to Something which takes a pointer to the starting object. We'll also make MyContainer a friend of Something:
class Something: IInterface
{
friend class MyContainer; // Can't test the code right now - may need to be MyContainer<T> or ::MyContainer<T> or something.
private:
T *x;
Something( T * first )
: x(first)
{
}
public:
T const& GetX()
{
return *x;
}
T& operator*()
{
return *x;
}
T* operator->()
{
return x;
}
Something& operator++()
{
++x;
return *this;
}
};
By making the constructor private, and setting the friend dependancy, we ensure that only MyContainer can make new Something iterators (this protects us iterating over random memory if something erroneous were given by a user).
Next off, we'll change MyContainer a little, so that rather than having an array of Something, we'll just have an array of T:
class MyContainer
{
...
private:
T *data;
};
Before we get to implementing begin and end, let's make that change to Container I talked about:
template<typename T, typename IteratorType>
class Container {
public:
...
// These prototype are the key. Notice the return type is IteratorType (value, not reference)
virtual IteratorType begin() = 0;
virtual IteratorType end() = 0;
};
So rather than relying on covariance (which would be really difficult in this case), we use a little template magic to do what we want.
Of course, since Container now accepts another type parameter, we need a corresponding change to MyContainer; namely we need to provide Something as the type parameter to Container:
template<class T>
class MyContainer : Container<T, Something>
...
And the begin/end methods are now easy:
template<class T>
MyContainer<T>::begin()
{
return Something(data);
}
template<class T>
MyContainer<T>::end()
{
// this part depends on your implementation of MyContainer.
// I'll just assume your have a length field in MyContainer.
return Something(data + length);
}
So this is what I've got for my midnight thinking. Like I mentioned above, I cannot currently test this code, so you might have to tweak it a bit. Hopefully this does what you want.
If the usage is supposed to be similar to stdlib, then the iterator needs to be a value object, because it normally gets copied by value a lot. (Also, otherwise what would the begin and end method return a reference to?)
template <class T>
class Iterator
{
shared_ptr<IIterator> it;
public:
Iterator(shared_ptr<IIterator>);
T& operator*() { it->deref(); }
T* operator->() { return &it->deref(); }
Iterator& operator++() { it->inc(); return *this; }
etc.
};

Using an abstract deleter with std::unique_ptr

I want to have a run-time interface that offers some creation methods. These methods return unique_ptr<T>, and I want to enable custom deletion by the creating class. The thing is that I definitely don't want the interface to offer these methods directly- they should only be available in the destruction of the unique_ptr<T, SomeCustomDel>. Now, I figured that I can use std::unique_ptr<T, std::function<void(T*)>>, but I'd really rather not because I simply don't need that level of abstraction and I don't want to have to pay the heap allocation.
Any suggestions?
Your specification isn't completely clear to me, but have you considered unique_ptr<T, void(*)(void*)>? This is a very flexible type with many qualities of a dynamic deleter.
If that isn't what you're looking for, you might try something along the lines of:
class impl
{
public:
virtual ~impl();
virtual void operator()(void*) = 0;
virtual void other_functionality() = 0;
};
class my_deleter
{
impl* p_;
public:
...
void operator()(void* p) {(*p_)(p);}
void other_functionality() {p_->other_functionality();}
...
};
It is difficult to know what is best in your case without more details about your requirements.
I wish there was a standard "dynamic" deleter version of std::unique_ptr. This mythical class would allow me to attach a deleter to the unique_ptr when I instantiate it, similar to std::shared_ptr.
That said if such a type existed I suspect it would essentially be implemented with std::unique_ptr<T,std::function<void(T*)>>. The very thing you wanted to avoid.
However I think you're underestimating std::function. Its implementation is optimization to avoid hitting the heap if possible. If your deleter object remains small everything will be done on the stack (I think boost::function can statically handle deleters up to 32 bytes in size).
A for the problem of a too general deleter. You have to provide the definition of the deleter. There is no way around that. However you don't have to let the user instantiate the class, which essentially forbids them from using it. To do this make the deleter's constructor(s) require a tag structure that is only defined in the implementation file.
Or possibly the simplest solution. Put the deleter in a detail namespace. The user is still free to use it, but it's obvious that they should not and can't complain when you change it, breaking their code.
I see two options.
Option 1: Use a custom deleter that contains a function pointer and optionally a raw char array to encode some state if necessary:
template<class T>
void simply_delete(T* ptr, const unsigned char*) {
delete ptr;
}
template<class T, int StateSize>
struct my_deleter {
void (*funptr)(T*,const unsigned char*);
array<unsigned char,StateSize> state;
my_deleter() : funptr(&simply_delete<T>) {}
void operator()(T* ptr) const {
funptr(ptr,StateSize>0 ? &state[0] : nullptr);
}
};
template<class T>
using upi = unique_ptr<T,my_deleter<T,sizeof(void*)>>;
Now, you can create different upi<T> objects that store different function pointers and deleter states without the need of mentioning what exactly is happening in its type. But this is almost the same as a function<> deleter which implements the "small function optimization". You can expect a decent standard library implementation to provide a very efficient function<> wrapper for small function objects (like function pointers) that don't require any heap allocations. At least I do. :)
Option 2: Simply use shared_ptr instead of unique_ptr and make use of its built-in type erasure feature with respect to deleters. This will also allow you to support Derived->Base conversions easily. For greatest control over what is allocated where you could use the std::allocate_shared function template.
This is a response to one of the answers, not to the original question. It is an answer instead of a comment simply because of formatting reasons.
I wish there was a standard "dynamic"
deleter version of std::unique_ptr.
This mythical class would allow me to
attach a deleter to the unique_ptr
when I instantiate it, similar to
std::shared_ptr.
Here is a start of an implementation of such a class. It is fairly easy to do. I've used unique_ptr only as an exception safety aid, nothing more. It is not as full-featured as you might like. These extra features are left as an exercise for the reader. :-) What is below establishes unique ownership of the pointer and storage for the custom dynamic deleter. Note that the smart pointer owns a passed-in pointer even if the constructor of the smart pointer throws (this is actually where unique_ptr is most useful in the implementation).
#include <memory>
#include <type_traits>
namespace detail
{
class impl
{
public:
virtual ~impl() {};
};
template <class T, class D>
class erase_type
: public impl
{
T* t_;
D d_;
public:
explicit erase_type(T* t)
noexcept(std::is_nothrow_default_constructible<D>::value)
: t_(t)
{}
erase_type(T* t, const D& d)
noexcept(std::is_nothrow_copy_constructible<D>::value)
: t_(t),
d_(d)
{}
erase_type(T* t, D&& d)
noexcept(std::is_nothrow_move_constructible<D>::value)
: t_(t),
d_(std::move(d))
{}
virtual ~erase_type()
{
if (t_)
d_(t_);
}
erase_type(const erase_type&) = delete;
erase_type& operator=(const erase_type&) = delete;
};
} // detail
template <class T>
class my_pointer
{
T* ptr_;
detail::impl* impl_;
public:
my_pointer() noexcept
: ptr_(nullptr),
impl_(nullptr)
{}
template <class Y>
explicit my_pointer(Y* p)
: ptr_(static_cast<T*>(p)),
impl_(nullptr)
{
std::unique_ptr<Y> hold(p);
impl_ = new detail::erase_type<Y, std::default_delete<Y>>(p);
hold.release();
}
template <class Y, class D>
explicit my_pointer(Y* p, D&& d)
: ptr_(static_cast<T*>(p)),
impl_(nullptr)
{
std::unique_ptr<Y, D&> hold(p, d);
typedef
detail::erase_type<Y, typename std::remove_reference<D>::type>
ErasedType;
impl_ = new ErasedType(p, std::forward<D>(d));
hold.release();
}
~my_pointer()
{
delete impl_;
}
my_pointer(my_pointer&& p) noexcept
: ptr_(p.ptr_),
impl_(p.impl_)
{
p.ptr_ = nullptr;
p.impl_ = nullptr;
}
my_pointer& operator=(my_pointer&& p) noexcept
{
delete impl_;
ptr_ = p.ptr_;
impl_ = p.impl_;
p.ptr_ = nullptr;
p.impl_ = nullptr;
return *this;
}
typename std::add_lvalue_reference<T>::type
operator*() const noexcept
{return *ptr_;}
T* operator->() const noexcept
{return ptr_;}
};
Note that unlike unique_ptr (and like shared_ptr), the constructors taking a pointer are not noexcept. Although that could possibly be mitigated via the use of a "small deleter" optimization. Yet another exercise left for the reader. :-)
I found this question googling my own problem; using unique_ptr with an abstract base class pointer. All the answers are great. I found #deft_code's one to be the best for my needs.
This is what I ended up doing in my case:
Suppose T is an abstract base class type. The makeT(), func creates a new instance of some derived class, and returns the T*:
std::unique_ptr<T, std::function<void(T*)>> p(makeT(), [](T* p){p.delete();});
I just wanted to share this for those who are looking for short, copy and pasteish solution.
For the untrained c++11 eyes, the [](... syntax is a lambda.
As is mentioned in the other answers, it's not a 'function pointer' in the C sense, but a callable c++ object, which is really tiny, and should have negligible overhead to carry it around.