I habe a Type A which gets passed by const reference into a scope where I need to make some computations on it. I have a whole group of utility functions that are associated to that type A and I wanted to bundle them up in a class that holds a reference/pointer/smartpointer to that A oject so I can extend my functionality locally without meddling with the already large interface of the type A.
So I created a type B holding a pointer to A whose creation can fail:
//! do not use outside of the scope where it was created
//! ensure sure that A lives longer than B.
class B{
A const * const _a;
B(A const& a) : _(&a){}
static bool checkValidity(const A&){
return true;
}
public:
B(const B&) = delete;
B(const B&&) = delete;
B& operator=( B&& other ) = delete;
B& operator=( const B& other ) = delete;
std::optional<B> create(A& a){
if(checkValidity(a))
return B(a);
return std::nullopt;
}
inline bool FooBar() const{
bool result = false;
//compute stuff based on _a
return result;
};
}
This works for me so far but i was wondering if maybe I should remove copyability and movability from the class to further limit the ways in which the local pointer can become invalid. So I deleted copy- and move assignment and copy/move construction.
However now I have issues constructing the optional.
As such I was wondering about what to do.
- make the constructor public and demand calling checkValidity prior to construction?
- return from the create function a type that can deal with nonmovable noncopyable objects?
- or just leave the object movable and let users of my class deal with the lifetime responsibility?
I tried using the pass-key idiom to give specific access to the optional-construction within the create function.
I failed to make it work.
I changed the return type of the create function to std::unique_ptr, that I managed to get compiling, but I wasn't sure if it was a decent approach as I don't intend for this B-Object to ever go out of the scope of the function where it was created in and I worried unique_ptr might imply that someone might be able to own it.
Because
Bcontains aconstfield. It not copy constructible. But the elision of the copy construction is still possible. You need that to construct thestd::optional<B>.If you delete the copy constructor, the
std::optional<B>cannot be constructed.Here you must declare:
Bcopy constructor is defaulted (the default here, is to have no copy constructor!), then only elision of the copy construction is possible.Notice that is is equivalent as your first code.