I am a bit embarrassed of asking such a simple question:
Is there any pointer class in cpp that initializes itself with nullptr but is 100% compatible to a basic c-stylish pointer?
to write:
extern "C" void someFunction(const Struct* i_s);
std::ptr<Struct> p;
// ...
p = new Struct;
// ...
someFunction(p);
Is there such a thing?
Or maybe in boost or Qt?
Edit: to make it clear: iam not searching for a smart pointer that takes ownership of the pointer and does ref counting.
You can use the following syntax
std::unique_ptr<Struct> up{};
(or std::shared_ptr). This way, the pointer is value-initialized, i.e. nullptr is being assigned to it.
See http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr for details about the default constructor.
If you looking for a "smart" pointer that just initialized by default with nullptr, then you can write a wrapper. A very basic version below:
#include <iostream>
template <typename T>
struct safe_ptr
{
T* _ptr;
explicit safe_ptr(T* ptr = nullptr):_ptr{ptr}{}
operator T*() const {return _ptr;}
safe_ptr& operator=(T* rhs)
{
_ptr = rhs;
return *this;
}
};
void test(int* p){}
int main()
{
safe_ptr<int> s;
if(s==nullptr)
std::cout << "Yes, we are safe!" << std::endl;
// test that it "decays"
test(s);
s = new int[10]; // can assign
delete[] s; // can delete
}
There is no such thing in C++ since all of the special pointer classes implement some form of ownership other than "maintained by someone else". You could technically use shared_ptr with an empty deleter but that adds reference counting you don't actually need.
The correct C++ solution is to just always add = 0; or = nullptr; to your raw pointer declarations that aren't initialized at declaration.
All that said, this question is tagged just as C++ so the idiomatic answer is to not use raw pointers in your code (except for non-owning cases obviously).
100% compatible to a basic c-stylish pointer
std::unique_ptr and std::shared_ptr do not have automatic conversions to a raw pointer, and that's a good thing as it would inevitably lead to horrible bugs. They take ownership, and in your comments you explicitly say:
the pointer should not take ownership of the given Pointer.
If you insist, you can define a "smart" pointer class yourself:
template <class T>
class RawPointer final
{
private:
T* raw_ptr;
public:
RawPointer(T* raw_tr) : raw_ptr(raw_ptr) {}
RawPointer() : raw_ptr(nullptr) {}
operator T*() const { return raw_ptr; }
};
struct Struct
{
};
void someFunction(const Struct* i_s);
int main()
{
RawPointer<Struct> p;
someFunction(p);
}
Is this a good idea? Probably not. You should just get into the habit of initializing your raw pointers:
Struct* p = nullptr;
On the other hand, people are thinking about a very similar addition to the standard library in the future. You may find A Proposal for the World’s Dumbest Smart Pointer an interesting read.
If this is really the behavior that you want, it would be trivial to implement it yourself in a template. Here's one such implementation:
template<class T>
class ptr_t{
T* ptr;
public:
ptr_t() : ptr(nullptr){ }
ptr_t(const ptr_t& other) : ptr(other.ptr){ }
ptr_t(T* other) : ptr(other){ }
T& operator*(){
return *ptr;
}
T* operator->(){
return ptr;
}
template<class U>
operator U(){
return (U)ptr;
}
}
However, the amount of convenience you will gain from such a device will be rather limited. You're probably much better off taking another approach.
Related
I wrote this template class for pointers usage
(I need smart pointers, but I can't use boost or C++11):
template<class T>
class TreePointer{
public:
TreePointer(){
isRefOnly=false;
data=NULL;
};
TreePointer(T* data){
this->data=data;
this->isRefOnly=false;
}
TreePointer(const TreePointer& anotherPtr){
this->data=anotherPtr.data;
this->isRefOnly=true;
}
virtual ~TreePointer(){
if (!isRefOnly){
delete data;
}
}
T* operator->() const{
return data;
}
void operator=(const TreePointer &anotherPtr){
this->data=anotherPtr.data;
this->isRefOnly=true;
}
private:
T* data;
bool isRefOnly;
};
And I have big class with many methods, like this:
class WrittenBigClassWithManyMethods{
public:
WrittenBigClassWithManyMethods(int v){
this->v=v;
}
int sum(WrittenBigClassWithManyMethods* a){
return v+a->v;
}
int v;
};
This usage of my smart pointers work perfectly:
TreePointer<WrittenBigClassWithManyMethods> tp(new WrittenBigClassWithManyMethods(5));
WrittenBigClassWithManyMethods* simpleClass=new WrittenBigClassWithManyMethods(5);
cout << tp->sum(simpleClass);
But it usage isn't work:
TreePointer<WrittenBigClassWithManyMethods> tp2(new WrittenBigClassWithManyMethods(5));
cout << tp->sum(tp2);
How i can change my template for pointers to make invoking methrod sum of class WrittenBigClassWithManyMethods with parameter of type TreePointer, without any changes for class WrittenBigClassWithManyMethods and its any usages? If this is not possible, how I minimize the changes for class WrittenBigClassWithManyMethods and its usage?
Usually you'll want to overload the unary operator * (de-reference) too, returning a T&. Then you can have both a reference and the original pointer by taking the address of the result:
tp1->method_that_takes_ref(*tp2); // With operator*()
tp1->method_that_takes_ptr(&*tp2); // Works, but syntax might be a bit surprising
Another way to get at the pointer inside would be to call operator -> directly, but that would be a bit awkward. You are likely better off providing some kind of "get" method, like the one in unique_ptr, that simply returns the raw pointer:
tp1->method_that_takes_ptr(tp2.operator->()); // Works, but ugh
tp1->method_that_takes_ptr(tp2.get()); // Much clearer
Add a conversion operator to T*:
operator T*() {
return data;
}
Now the compiler will call it whenever it wants to convert a TreePointer<SomeClass> to a SomeClass*.
I'm currently working on some code using smart pointers in which it is necessary at a number of points to cast these pointers to their base types and pass them as const arguments to functions. Currently I'm using shared_ptr's and the standard pointer casting functions to achieve this, but this seems inefficient (as each cast costs at least one CAS) and also misleading (as we are not modelling a shared relationship, the parent is the sole owner of the object).
I therefore came up with the following but wanted to check it is indeed safe, or is there some edge case which will break it?
template <typename ToType, typename FromType>
class FTScopedCastWrapper {
public:
explicit FTScopedCastWrapper(std::unique_ptr<FromType>& p) : from_ptr_(&p) {
auto d = static_cast<ToType *>(p.release());
to_ptr_ = std::unique_ptr<ToType>(d);
}
~FTScopedCastWrapper() {
auto d = static_cast<FromType *>(to_ptr_.release());
(*from_ptr_) = std::unique_ptr<FromType>(d);
}
const std::unique_ptr<ToType>& operator()() {
return to_ptr_;
}
// Prevent allocation on the heap
void* operator new(size_t) = delete;
void* operator new(size_t, void*) = delete;
void* operator new[](size_t) = delete;
void* operator new[](size_t, void*) = delete;
private:
std::unique_ptr<FromType>* from_ptr_;
std::unique_ptr<ToType> to_ptr_;
};
template <typename ToType, typename FromType>
FTScopedCastWrapper<ToType, FromType> FTScopedCast(std::unique_ptr<FromType>& p) {
return FTScopedCastWrapper<ToType, FromType>(p);
}
The intended usage is then
void testMethod(const std::unique_ptr<Base>& ptr) {
// Do Stuff
}
auto ptr = std::make_unique<Derived>();
testMethod(FTScopedCast<Base>(ptr)());
The deleter is not carried across as doing so would prevent upcasting. It also doesn't make sense to do so as the deleter will never be invoked on the created smart pointer anyway.
Allocation on the heap is prevented as it could allow the wrapper to outlive the pointer it wraps, copying is prevented by the std::unique_ptr member and standard destruction order will ensure the raw pointer is returned to the original smart pointer before it is destroyed, even if it is declared in the same scope as the wrapper.
I'm aware this is not thread safe but I'd argue sharing a unique_ptr between threads is breaking its contract of a single owner.
If I understand you correctly, the intention is to "steal" the contents of a std::unique_ptr for the duration of the function call, and then return it to its original owner when the function call is complete.
But this just seems needlessly convoluted. For a start, as pointed out by #TheUndeadFish in the comments, you could just take a raw Base* as the function argument and call it with std::unique_ptr::get(). As long as the called function doesn't do something silly like call delete on the passed-in pointer or squirrel it away in a static variable for later use then this will work just fine.
Alternatively, if you find raw pointers completely distasteful, you could use a non-owning pointer wrapper, something like the following (untested, but you get the idea):
template <typename T>
class unowned_ptr {
public:
unowned_ptr() = default;
unowned_ptr(const unowned_ptr&) = default;
unowned_ptr& operator=(const unowned_ptr&) = default;
template <typename U>
unowned_ptr(const U* other) : ptr(other) {}
template <typename U>
unowned_ptr(const std::unique_ptr<U>& other) : ptr(other.get()) {}
T* operator->() { return ptr; }
const T* operator->() const { return ptr; }
private:
T* ptr = nullptr;
};
Something very similar to this, std::observer_ptr ("the world's dumbest smart pointer") was proposed for C++17, but I'm not sure of the status.
I'm implementing for practice a smart pointer class.
I already defined an assignment operator overload that takes another instance of the same class. Now I want to define an overload of this operator, that takes any pointer. So I should be able to do stuff like smartPointer = &someObject; or smartPointer = NULL;, etc.
How can I go about doing that? Should I pass in a void*? Something else?
As a more general question (and I know this is rarely desired): what kind of parameter tells the compiler that any pointer can be passed in?
You can use a template function to make your object allow any pointer to be assigned to it.
template<typename T>
void operator=(T* obj)
{
//Your code here
}
However, its not a smart pointer if you could assign it any raw pointers as it could be assigned to more than one smart pointer object and then there would be a problem while deleting the pointer.
Following may help:
class MySharedPointer
{
public:
template <typename T>
MySharedPointer& operator = (T* p)
{
ptr.reset(p, [](void* p) { delete static_cast<T*>(p); });
return *this;
}
// nullptr is not a pointer, so it should have its own overload.
MySharedPointer& operator = (std::nullptr_t) {
ptr.reset();
return *this;
}
private:
std::shared_ptr<void> ptr;
};
Live example
I am creating a class which interops with some Windows API code, now one of the pointers I have to initialize is done by calling a native function which initializes it.
My pointers are of type std::unique_ptr with a custom deleter, which calls the WinAPI deleter function provided, however I cannot pass the unique_ptr with the & address-of operator to the init-function. Why?
I have created a sample that demonstrates my problem:
#include <memory>
struct foo
{
int x;
};
struct custom_deleter {};
void init_foo(foo** init)
{
*init = new foo();
}
int main()
{
std::unique_ptr<foo, custom_deleter> foo_ptr;
init_foo(&foo_ptr);
}
The compiler barks and says:
source.cpp: In function 'int main()':
source.cpp:19:21: error: cannot convert 'std::unique_ptr<foo, custom_deleter>*' to 'foo**' for argument '1' to 'void init_foo(foo**)'
Somewhere under the covers, unique_ptr<foo> has a data member of type foo*.
However, it's not legitimate for a user of the class to directly modify that data member. Doing so would not necessarily preserve the class invariants of unique_ptr, in particular it wouldn't free the old pointer value (if any). In your special case you don't need that to happen, because the previous value is 0, but in general it should happen.
For that reason unique_ptr doesn't provide access to the data member, only to a copy of its value (via get() and operator->). You can't get a foo** out of your unique_ptr.
You could instead write:
foo *tmp;
init_foo(&tmp);
std::unique_ptr<foo, custom_deleter> foo_ptr(tmp);
This is exception-safe for the same reason that std::unique_ptr<foo, custom_deleter> foo_ptr(new foo()); is exception-safe: unique_ptr guarantees that whatever you pass in to its constructor will eventually get deleted using the deleter.
Btw, doesn't custom_deleter need an operator()(foo*)? Or have I missed something?
Steve has already explained what the technical problem is, however, the underlying problem goes much deeper: The code employs an idiom helpful when you deal with naked pointers. Why does this code do two-step initialization (first create the object, then initialize it) in the first place? Since you want to use smart pointers, I'd suggest you carefully adapt the code:
foo* init_foo()
{
return new foo();
}
int main()
{
std::unique_ptr<foo, custom_deleter> foo_ptr( init_foo() );
}
Of course, renaming init_foo() to create_foo() and having it return a std::unique_ptr<foo> directly would be better. Also, when you use two-step initialization, it's often advisable to consider using a class to wrap the data.
You can use the following trick:
template<class T>
class ptr_setter
{
public:
ptr_setter(T& Ptr): m_Ptr{Ptr} {}
~ptr_setter() { m_Ptr.reset(m_RawPtr); }
ptr_setter(const ptr_setter&) = delete;
ptr_setter& operator=(const ptr_setter&) = delete;
auto operator&() { return &m_RawPtr; }
private:
T& m_Ptr;
typename T::pointer m_RawPtr{};
};
// Macro will not be needed with C++17 class template deduction.
// If you dislike macros (as all normal people should)
// it's possible to replace it with a helper function,
// although this would make the code a little more complex.
#define ptr_setter(ptr) ptr_setter<decltype(ptr)>(ptr)
and then:
std::unique_ptr<foo, custom_deleter> foo_ptr;
init_foo(&ptr_setter(foo_ptr));
I eventually came up with an approach that allows to initialise unique_ptr's with a code like this:
struct TOpenSSLDeleter { ... }; // Your custom deleter
std::unique_ptr<EVP_MD_CTX, TOpenSSLDeleter> Ctx;
...
Ctx = MakeUnique(EVP_MD_CTX_create()); // MakeUnique() accepts raw pointer
And here is the solution:
template <class X>
struct TUniquePtrInitHelper {
TUniquePtrInitHelper(X *Raw) noexcept {
m_Raw = Raw;
}
template <class T, class D>
operator std::unique_ptr<T, D>() const noexcept {
return std::unique_ptr<T, D>(m_Raw);
}
private:
X *m_Raw;
};
template <class X>
TUniquePtrInitHelper<X> MakeUnique(X *Raw) noexcept {
return {Raw};
}
I'd like a pointer wrapper class that acts just like a raw pointer but also saves a special integer along with the pointer (Type's index in the array it came from)
I managed to have it behave mostly like a pointer. I am aware that the pointer comparison solution might not be optimal but that's not my main problem.
I want the wrapper to be constructed with 2 parameters(pointer,indexToArr), unless the pointer is NULL - then I don't care about indexToArr.
The problem I'm trying to solve is how to allow returning NULL just like a normal pointer allows.
current solution uses an ASSERT. But I want something that works in compile-time. something in the spirit of a specialized template method - allowing only NULL as its argument.
Current version:
class PtrWrapper
{
public:
PtrWrapper(Type* ptr, int indToArr)
: m_ptr(ptr), m_indexToArr(indToArr){}
//allow returning NULL, only NULL
PtrWrapper(Type* ptr) : m_ptr(NULL), m_indexToArr(-1) {ASSERT(ptr == NULL);}
Type* operator->() const {return m_ptr;}
Type& operator*() const {return *m_ptr;}
int IndexToArr() const {return m_indexToArr;}
//for pointer comparison
operator Type*() const {return m_ptr;}
private:
Type* m_ptr;
int m_indexToArr;
};
Any ideas, suggestions?
Thanks,
Leo
template<typename Type>
class PtrWrapper
{
typedef struct { } NotType;
public:
Ptr() { }
Ptr(const NotType* nullPtr) { }
Ptr(Type* p, int index) { }
};
You can exploit the fact that literal NULL / 0 can be auto-cast to any pointer type. Create a type that is NOT T, and a constructor which takes a single pointer to that type which nobody will ever use. Now you can handle PtrWrapper<T> x(NULL); explicitly.
Of course as others have said, this is only going to work if NULL is known at compile-time.
Simply make a default constructor with no arguments that initializes your pointer to NULL, but make sure to have some checks in your operator* and operator-> for a NULL pointer.
Do the following:
PtrWrapper(Type* ptr) : m_ptr(ptr), m_indexToArr(0) {ASSERT(ptr != NULL);}
PtrWrapper() : m_ptr(NULL), m_indexToArr(-1) {ASSERT(ptr == NULL);}