I am creating a pointer class, but I can't figure out how to return the value (address of the object pointed to) of the raw pointer handled by my class. My class is like this.
template<typename T>
class Ptr {
public:
Ptr(T t) :p{&t} { }
T* operator->() { return p; }
T& operator*() { return *p; }
T& operator[](int i) { return p[i]; }
private:
T* p;
};
If I will do:
int x = 42;
Ptr<int> y = x;
std::cout << y; //should print the address (y.p).
I absolutely don't know what operator to overload so if I use "y" in any expression it will return the address of the object pointed to, just like what a raw pointer does. What should I do?
First off, your code has a bug. Your constructor is taking t by value, which means that p will store the address of the temporary t which will die at constructor exit (and the pointer will become dangling). You probably want this:
Ptr(T &t) : p{&t} {}
Even so, this means your pointer wrapper will be initialised by objects and not by pointers, which looks counter-intuitive. I'd change the constructor to accept a T*.
Second, you're asking how to get the "address of the raw pointer," but I assume you really want the "address stored in the raw pointer."
With this out of the way, let's turn to your question. There are several ways you can approach this.
One is to give your class an implicit conversion to T*, like this:
operator T* () const
{ return p; }
That way, an implicit conversion from Ptr<T> to T* will exist and the compiler will use it wherever necessary, but that may be a bit more than you want.
A more restricted version is to make the conversion explicit:
explicit operator T* () const
{ return p; }
Now you have to cast to the pointer explicitly:
std::cout << static_cast<int*>(y);
You can follow the pattern used by std smart pointers and provide a get() function:
T* get() const
{ return p; }
std::cout << y.get();
Finally, if you only want this functionality for streaming, you can just overload operator<< for your class:
template <class T, class Char, class Traits>
std::basic_ostream<Char, Traits>& operator<< (std::basic_ostream<Char, Traits> &stream, const Ptr<T> &ptr)
{
return stream << ptr.operator->(); // or ptr.get(), if you implement it
}
You should overload operator T*().
Note that the pointer you're storing is a pointer to the parameter and becomes invalid as soon as the constructor returns, so dereferencing it anywhere causes your program to be undefined.
You probably want
Ptr(T* t) : p{t} { }
and
Ptr<int> y = &x;
Related
If I want, for const correctness, to overload a class member returning a member pointer, what is exactly the difference between a const std::shared_ptr<T> and std::shared_ptr<const float>? For instance, in the following class:
class A {
public:
A() {}
/* */
std::shared_ptr<float> getMemberPtr() { return std::shared_ptr<float>(member); }
const std::shared_ptr<float> getMemberPtr() const { return std::shared_ptr<float>(member); }
std::shared_ptr<const float> getMemberPtr() const { return std::shared_ptr<const float>(member); }
/* */
void setMember(float _val) { member = _val; }
protected:
float member;
};
Does calling the second overload will change the type of the object it is pointed to, not allowing the setter method to be called afterwards? If not, what exactly is the difference between both return types, and what is the better practice?
Does casting shared_ptr to shared_ptr changes the object it is pointed to?
No. Casting a pointer does not change the pointed object.
what exactly is the difference between both return types
It is not possible to modify the pointed object through a pointer to const. It is possible to modify the pointed object through a pointer to non-const.
Note that shared pointer does not have a constructor that accepts a float, so the example program is ill-formed.
Returning a const object (const std::shared_ptr<float>) rarely makes any sense.
As I understand C++ Core Guidelines by Bjarne Stroustrup & Herb Sutter, it is a good idea to use pointers this way:
unique_ptr for the good old clear one ownership
shared_ptr for truly shared ownership by design
weak_ptr when by design the pointer might not be valid anymore
raw pointer whenever the pointer is valid by design, and ownership is unchanged
Thus theoretically it still may be a common bug that a raw pointer becomes invalid (see R37).
I wonder if there is a way for debug/QA purposes, to make an assertion of the validity of the raw pointer. I believe such checks can help improve stability of programs dramatically.
I have written the following possible implementation. My question:
What do you think about having such code? Does it make sense to you? Does something like this exist? Any other comments?
At this stage incompleteness of the implementation is not so important (thread safety or other stuff), unless it reflects a reason for not doing it.
#include <memory>
#include <cassert>
#if NDEBUG
template <typename T>
using WatchedPtr = T*;
template <typename T>
T* get (const std::shared_ptr<T>& p) {return p.get();}
#else
template <typename T>
class WatchedPtr {
template <typename T1>
friend WatchedPtr<T1> get (const std::shared_ptr<T1>& p);
public:
WatchedPtr() : _ptr (nullptr) {}
operator T* () { return getPtr();}
T* operator->() const { assert (getPtr()); return getPtr(); }
T& operator*() const { assert (getPtr()); return *getPtr(); }
private:
T* getPtr () const { return _weak.expired () ? nullptr : _ptr;}
WatchedPtr(std::shared_ptr<T> p) : _weak (p) {
_ptr = _weak.lock().get();
}
std::weak_ptr<T> _weak;
T* _ptr;
};
template <typename T1>
inline WatchedPtr<T1> get (const std::shared_ptr<T1>& p) {return WatchedPtr<T1> (p);} //because I cannot change the get() member
#endif
Usage example:
void f (WatchedPtr<int> p) {
assert(p);//detects errors
*p = 3;//detects errors
std::cout << "f: *p=" << *p << std::endl;
}
void g (int* p) {
assert(p);//detects errors
*p = 3;//does not detect error
std::cout << "g: *p=" << *p << std::endl;
}
int main () {
WatchedPtr<int> p;
{
auto pp = std::make_shared<int> (1234);
p = get(pp);
f (p);
}
f (p);
g (p); //the internal assert() of g() will detect errors, because casting of invalid p to raw pointer will be nullptr
}
*I thought of implementing also for unique_ptr. But so far my only idea is to store a pointer to unique_ptr in WatchedPtr. This will identify errors only on some of the cases, where get() or bool operator will crash or return nullptr.
I have the template class data_ptr which has the member operator * for access to the pointer to data:
operator T*() { return m_pPtr; }
Also inside the constructor of data_ptr its pointer is "pinned" in memory and in destructor is "unpinned".
I want to forbid using the operator* is this way:
data_ptr<T> GetSomeDataPtr { return data_ptr<T>(...); }
T *pRawPointerToData = *GetSomeDataPtr();
... because the function GetSomeDataPtr returns the temporary object data_ptr, and when the destructor gets called its data pointer becomes invalid, so we get a crash when accessing the pRawPointerToData.
So, the main idea is to use compiler to find such code. I am using Visual Studio 2015 Update 3.
Example:
template <class T> class data_ptr
{
public:
data_ptr(T val) : p(new T(val)) {}
~data_ptr() {delete p;}
operator T*() { return p; }
private:
T *p;
};
template <class T>
data_ptr<T> GetSomeDataPtr(T val)
{
return data_ptr<T>(val);
}
int main()
{
int &rawReferenceToData = *GetSomeDataPtr<int>(123);
rawReferenceToData = 456; // << invalid access to already deleted object!
return 0;
}
You can declare operator T* with an lvalue ref-qualifier, i.e.
operator T*() & { return p; }
so that this conversion can be called only for a lvalue of data_ptr, which means a temporary (rvalue) is forbidden to call this conversion.
There are also some defects with your design. Even if an object is not a temporary, it will be destroyed later at some time, and those T*s previously exposed do not know the destroy, which has potential danger of invalid access. As a result, it is the caller's responsibility to guarantee no invalid access, so you don't have to limit this call for temporary objects. As an example, std::string::c_str does not have such limitations.
Is it possible to cast from a predefined Type_pointer in c++ to its Type?
For example we defined a custom XType.
I want to do something like this, but I get an error:
XType* b;
XType a = (XType) b;
I want to pass the pointer itself to a function that only accept Type (not Type*)
You should dereference the pointer with the * operator:
struct Type {
Type(Type*) {}
};
void f(Type t) {
}
int main () {
Type a;
Type* b = &a;
// Q: how to invoke f() if I only have b?
// A: With the dereference operator
f(*b);
}
In addition to the #Robᵩ's proposal, you can change the function to accept the pointer.
Actually, if you plan to pass the pointer to other functions from within the given function, you must get the pointer (well, or a reference) as parameter, otherwise you'll get a copy of the original object as the parameter, so you'll be unable to retrieve the address of (i.e. pointer to) the original object.
If you'd like to spare the refactoring, you can do the reference trick:
void g(T* pt)
{
// ...
}
void f(T& rt) // was: void f(T rt)
{
cout << rt.x << endl; // no need to change, syntax of ref access
// is the same as value access
g(&rt); // here you get the pointer to the original t
}
T* t = new T();
f(t);
I define two versions of overloaded operator[] function in a class array. ptr is a pointer to first element of the array object.
int& array::operator[] (int sub) {
return ptr[sub];
}
and
int array::operator[] (int sub) const {
return ptr[sub];
}
Now, if I define a const object integer1 the second function can only be called..... but if I make a non-const object and then invoke as below:
cout << "3rd value is" << integer1[2];
which function is called here?
In your second example, the non-const version will be called, because no conversion is required, and a call that requires no conversion is a better match than one that requires a conversion.
Ultimately, however, you have a basic problem here: what you really want is behavior that changes depending on whether you're using your object as an rvalue or an lvalue, and const doesn't really do that. To make it work correctly, you normally want to return a proxy object, and overload operator= and operator T for the proxy object:
template <class T>
class myarray {
T *ptr;
class proxy {
T &val;
proxy &operator=(proxy const &p); // assignment not allowed.
public:
proxy(T &t) : val(t) {}
operator T() const { return val; }
proxy &operator=(T const&t) { val = t; return *this; }
};
proxy const operator[](int sub) const { return proxy(ptr[sub]); }
proxy operator[](int sub) { return proxy(ptr[sub]); }
// obviously other stuff like ctors needed.
};
Now we get sane behavior -- when/if our array<int> (or whatever type) is const, our operator[] const will be used, and it'll give a const proxy. Since its assignment operators are not const, attempting to use them will fail (won't compile).
OTOH, if the original array<int> was not const, we'll get a non-const proxy, in which case we can use both operator T and operator=, and be able to both read and write the value in the array<int>.
Your const version should return const int& not int, so that the semantics are just the same between the two functions.
Once you've done that, it doesn't matter which one is used. If the const version has to be used because your object has a const context, then it will be... and it won't matter as you're not trying to modify anything. Otherwise, it'll use the non-const version... but with just the same effect.