Нарешті, з'явилось трохи часу, щоб дописати нормальну відповідь.
1. Щодо union'ів. Технічних причин, чому б не можна було union використовувати як base-class, я не бачу. Наразі, це просто заборонено і все. Тобто, можливо причина в тому, що всі класи, які можна успадкувати, в С++ підтримують віртуальність (тобто може мати прихований вказівник на vmt), а union через його природу такий вказівник не зможе містити безпечно. Це моя спроба копнути чуть глибше, посилаючись на деталі реалізації. Що там собі думає комітет - я хз. Думаю, все зводиться до того, що union'и просто дуже погано підтримуються в С++ і існують лише для збереження сумісності з С. А, нормально ввести їх у С++ дядькам з комітету просто влом, вже неодноразово union'и щось ламали, але маємо, що маємо.
2. Глянув я на ці ваші проперті в С# і ось що вийшло у мене
template <typename T> struct Getter {
Getter(T& v) : v_{v} { }
operator T() const { return v_; }
protected:
T& v_;
};
template <typename T> class Property : public Getter<T> {
using Getter<T>::v_;
using Getter<T>::Getter;
public:
Property<T>& operator=(T v) {
v_ = v;
return *this;
}
};
class Foo {
int* ptr_ = nullptr;
public:
Foo() : ptr{ptr_} {}
Property<int*> ptr; // set/get
};
int main() {
int a = 7;
std::cout << "a = " << a << std::endl;
Foo foo;
foo.ptr = &a;
int* ptr_a1 = foo.ptr;
// int*& ptr_a2 = foo.ptr; // error is ok
int* const ptr_a3 = foo.ptr;
int* const& ptr_a4 = foo.ptr;
std::cout << "a = " << a << std::endl;
std::cout << "ptr_a1 = " << ptr_a1 << std::endl;
std::cout << "ptr_a3 = " << ptr_a3 << std::endl;
std::cout << "ptr_a4 = " << ptr_a4 << std::endl;
*foo.ptr = 3;
std::cout << "a = " << a << std::endl;
int b = *foo.ptr;
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
}
https://rextester.com/PAUDI7530
P.S. - думаю, можна зробити ще краще, але потрібно більше деталей (а-ля ТЗ)