operator->) in C++Goal. Understand how to implement operator-> correctly for wrappers and iterators, with modern C++ practices (const-correctness, exception guarantees, and clear ownership).
operator-> must returnThe result of operator-> must either be:
T* or const T*), oroperator-> (the resolution recurses until a pointer is produced).That design allows seamless member access like obj->member().
This example wraps a pointer to Triple and controls access, but uses modern headers, int main(), and const-correct overloads.
#include <iostream>
struct Triple {
int i, j, k;
void print() const {
std::cout << "\ni = " << i
<< ", j = " << j
<< ", k = " << k;
}
};
// Thin wrapper that optionally grants access to the underlying Triple
class TPtr {
bool access_;
Triple* ptr_; // educational: raw pointer with trivial lifetime rules
public:
TPtr(bool access, Triple* p) : access_(access), ptr_(p) {}
// const and non-const overloads; noexcept because it just returns a pointer
Triple* operator->() noexcept {
return access_ ? ptr_ : nullptr;
}
const Triple* operator->() const noexcept {
return access_ ? ptr_ : nullptr;
}
};
int main() {
Triple a{1,2,3}, b{4,5,6};
TPtr ta(false, &a), tb(true, &b);
if (ta.operator->() != nullptr) ta->print(); // no access → nullptr, guard if needed
if (tb.operator->() != nullptr) tb->print(); // access granted
}
operator-> for an iteratorCustom iterators usually provide both operator* and operator->. The latter should return a pointer to the element so member access is natural:
template <class T>
class SimpleIter {
T* p_ = nullptr;
public:
using value_type = T;
using reference = T&;
using pointer = T*;
using difference_type = std::ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
explicit SimpleIter(T* p) : p_(p) {}
reference operator*() const noexcept { return *p_; }
pointer operator->() const noexcept { return p_; }
// ... ++, --, +, -, ==, <, etc. as needed
};
operator-> should be noexcept and fast; it typically just returns an address.std::unique_ptr<T> or std::shared_ptr<T> internally and return get() from operator->.nullptr, throw, or an explicit status check.operator-> a simple gateway to the pointee; heavy policy checks belong elsewhere.This keeps the spirit of the original example while fixing headers and main, and using nullptr on denied access.
#include <iostream>
struct Triple {
int i, j, k;
void print() const {
std::cout << "\ni = " << i
<< ", j = " << j
<< ", k = " << k;
}
};
class TPtr {
bool access_;
Triple* ptr_;
public:
TPtr(bool access, Triple* p) : access_(access), ptr_(p) {}
Triple* operator->() noexcept { return access_ ? ptr_ : nullptr; }
const Triple* operator->() const noexcept { return access_ ? ptr_ : nullptr; }
};
int main() {
Triple a{1,2,3}, b{4,5,6};
TPtr ta(false, &a), tb(true, &b);
if (tb.operator->() != nullptr) tb->print();
}
vector class so the operator implements an iterator.