Wrong context when calling method - c++

How can I achieve that CoroutineManager::Routine() calls Operator::Worker() ?
Worker() must be called by Routine() in this test scenario.
So the question is whether how C++ handle the context. The Routine() method must not implemented by the Operator class itself.
template <class T>
class CoroutineManager {
private:
T var;
int _a, _b;
public:
CoroutineManager(int a, int b);
T Worker();
void Routine();
};
template <class T>
CoroutineManager<T>::CoroutineManager(int a, int b) {
this->_a = a;
this->_b = b;
}
template <class T>
T CoroutineManager<T>::Worker() {
std::cout << "wrong method" << std::endl;
return var;
}
template <class T>
void CoroutineManager<T>::Routine() {
std::cout << this->Worker() << std::endl;
}
class Operator : public CoroutineManager<double> {
using CoroutineManager::CoroutineManager;
public:
Operator(int a, int b) : CoroutineManager(a,b) {};
virtual double Worker();
};
double Operator::Worker() {
return 3.141;
}
// MARK: -
int main(int argc, const char * argv[]) {
Operator *op = new Operator(3,4);
op->Routine();
return 0;
}

I've changed the code to fulfill my requirements, but maybe there are exists more straight forward solutions(?). It's only about Worker and Worker2, two different methods in two objects which can be called by the derived Routine method without the boundaries of inheritance context:
// MARK: -
template <typename T, typename V>
class CoroutineManager {
private:
V _a, _b;
V (T::*workerPtr)();
T *cm;
public:
CoroutineManager(V a, V b) {
this->_a = a;
this->_b = b;
}
void Routine() {
std::cout << (*cm.*workerPtr)() << std::endl;
}
void SetWorker(T *cm, V (T::*ptr)()) {
this->workerPtr = ptr;
this->cm = cm;
}
V getA() {
return this->_a;
}
V getB() {
return this->_b;
}
};
// MARK: -
class Operator : public CoroutineManager<Operator,int> {
private:
int xx;
public:
Operator(int a, int b) : CoroutineManager(a,b) {
this->xx = a*2 + b*2;
};
int Worker();
};
int Operator::Worker() {
return getA() * getB() + this->xx;
}
// MARK: -
class Operator2 : public CoroutineManager<Operator2,double> {
public:
Operator2(double a, double b) : CoroutineManager(a,b) {};
double Worker2();
};
double Operator2::Worker2() {
return getA() + getB();
}
// MARK: -
int main(int argc, const char * argv[]) {
Operator *op = new Operator(4,4);
int (Operator::*workerPtr)() = &Operator::Worker;
op->SetWorker(op, workerPtr);
op->Routine();
Operator2 *op2 = new Operator2(3.14,2.78);
double (Operator2::*workerPtr2)() = &Operator2::Worker2;
op2->SetWorker(op2, workerPtr2);
op2->Routine();
return 0;
}
Output:
32
5.92
Program ended with exit code: 0

Related

How can I decrease the number of overloaded functions

I want to know if there is an approach to decrease the number of overloaded function (function edit) in the below code.
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit(int new_a);
void edit(char new_b);
void edit(float new_c);
void edit(int new_a, char new_b);
void edit(int new_a, float new_c);
void edit(char new_b, float new_c);
void edit(int new_a, char new_b, float new_c);
void info();
private:
int a;
char b;
float c;
};
Here is the implementation of the edit functions :
void foo::edit(int new_a)
{
a = new_a;
}
void foo::edit(char new_b)
{
b = new_b;
}
void foo::edit(float new_c)
{
c = new_c;
}
void foo::edit(int new_a, char new_b)
{
a = new_a;
b = new_b;
}
void foo::edit(int new_a, float new_c)
{
a = new_a;
c = new_c;
}
void foo::edit(char new_b, float new_c)
{
b = new_b;
c = new_c;
}
void foo::edit(int new_a, char new_b, float new_c)
{
a = new_a;
b = new_b;
c = new_c;
}
The edit function will let the user change the parameters of the object as he wishes.
But the thing is that if we add a new parameter we have to add to many overloaded function and I thought there should be a better way.
Here with 3 parameters we need 7 overloaded functions but if we had 4 parameters (a, b, c and d) then we had to develop 14 overloaded function!
That's why I think there should be a better approach.
Thanks.
With variadic and (ab)using std::get<T> on std::tuple, you might do
template <typename... Ts>
void edit(Ts... values)
{
((std::get<Ts&>(std::tie(a, b, c)) = std::get<Ts&>(std::tie(values...))), ...);
}
Demo.
Note: I use std::get<Ts&>(std::tie(values...)) instead of simply values to get error with duplicated input types(edit(42, 42);).
You can avoid the huge number of overloads and still allow the caller to set more than one member in a single expression:
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
foo& edit(int new_a) { a = new_a; return *this;}
foo& edit(char new_b) { b = new_b; return *this; }
foo& edit(float new_c) { c = new_c; return *this; }
private:
int a;
char b;
float c;
};
int main() {
foo f(1,'c',2.0);
f.edit(42).edit(42.0f).edit('a');
}
Adding a member requires you to write one overload rather than N to support all combinations.
The previous solutions are quite fine, but suppose that all elements have a different type.
A possibility is to still use a variadic template, and in the call to indicate with a string which element must be modified.
This would allow the possibility to have the same type for different elements.
#include <iostream>
#include <string>
class foo {
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit() {};
template<typename T1, typename... T2>
void edit (const std::string& id, T1 var1, T2... var2) {
if (id == "a") a = var1;
else if (id == "b") b = var1;
else if (id == "c") c = var1;
edit(var2...);
};
void info();
//private:
int a;
char b;
float c;
};
std::ostream& operator<<(std::ostream& os, const foo& obj) {
std::cout << "a = " << obj.a << " b = " << obj.b << " c = " << obj.c;
return os;
}
int main() {
foo example(1, 'a', 2.0);
example.edit("c", 3.0f, "b", 'g', "a", 5);
std::cout << example << std::endl;
}
Given your edit functions that modify a single member:
void edit(int new_a)
{
a = new_a;
}
void edit(char new_b)
{
b = new_b;
}
void edit(float new_c)
{
c = new_c;
}
You can define a single function in C++11 using variadic templates to support multiple parameters in terms of multiple calls with a single parameter:
template< typename FirstType, typename ...OtherTypes >
void edit(FirstType ft, OtherTypes ...ot)
{
edit(ft);
edit(ot...);
}
Using C++17, fold expressions can make this function even simpler.
template< typename ...Types >
void edit(Types ...types)
{
(edit(types), ...);
}
Note: This solution will not try to prevent multiple changes to the same type, such as edit(1, 2, 3);

Definite methods with parameters from variadic templates

I would like to define a variadic template class BaseA, which has a variadic function execute(...). The subclasses extend execute(...) with definite arguments.
I try a demo code, but it has type conversion error, how to collect all subclasses and use execute?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// template base class A
template <typename ... Types>
class BaseA {
public:
virtual int execute(Types ...) = 0;
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
int execute(int b) override {
//...
printf("sub-1 has int %d", b);
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, string> {
public:
int execute(int b, string c) override {
//...
printf("sub-2 is int:%d and str:%s", b, c.c_str());
return 0;
}
};
// SubA3 may has other arguments
int main() {
vector<BaseA<int> *> as(3);
as[0] = (BaseA<int> *) new SubA1();
as[1] = (BaseA<int, string> *) new SubA2(); // error here
as[0]->execute(1);
as[1]->execute(1, "2");
// as[2] ...
return 0;
}
Thanks for any ideas.
Use another base for the array and typecast when using.
#include <iostream>
#include <string>
#include <vector>
class BaseAA {
public:
BaseAA(){
}
~BaseAA(){
}
template <typename ... Types>
int executeAA(Types ...){
std::cout << "BaseAA";
return 0;
}
};
// template base class A
template <typename ... Types>
class BaseA: public BaseAA {
public:
using BaseType = BaseA<Types...>;
virtual int execute(Types ... ts){
std::cout << "BaseA ";
return executeAA<Types ...>(ts...);
};
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
int execute(int b) override {
//...
BaseType::execute(b);
std::cout << "sub-1 has int " << b << '\n';
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, std::string> {
public:
int execute(int b, std::string c) override {
//...
BaseType::execute(b, c);
std::cout << "sub-2 is int:"<<b<<" and str:" << c;
return 0;
}
};
// SubA3 may has other arguments
int main() {
std::vector<BaseAA *> as(3);
as[0] = new SubA1();
as[1] = new SubA2(); // error here
static_cast<SubA1::BaseType*>(as[0])->execute(1);
static_cast<SubA2::BaseType*>(as[1])->execute(1, "2");
// as[2] ...
return 0;
}
If you don't want the typecast then you can use a single parameter type
with derived classes for the different groups of parameters.
#include <iostream>
#include <vector>
#include <tuple>
using namespace std::string_literals;
template <class O, class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_this(O* o, F&& f, Tuple&& t, std::index_sequence<I...>) {
return (o->*f)(std::get<I>(t)...);
}
struct ParamsBase {
};
class BaseAA {
public:
BaseAA(){
}
~BaseAA(){
}
virtual int execute(const ParamsBase& p) = 0;
};
template<typename ... Ts>
struct Params: public ParamsBase {
using Tuple_t = std::tuple<Ts...>;
static size_t const count = sizeof ... (Ts);
Tuple_t p;
Params(Tuple_t&& p): p(p){
}
static Params const& getParams(const ParamsBase& p) {
return static_cast<const Params&>(p);
}
static Tuple_t const& getTuple(const ParamsBase& p) {
return getParams(p).p;
}
};
// template base class A
template <typename ... Types>
class BaseA: public BaseAA {
public:
using Params_t = Params<Types...>;
virtual int execute(const ParamsBase& pin) override {
return apply_this(this, (int(BaseA::*)(Types...))(&BaseA::execute), Params_t::getTuple(pin), std::make_index_sequence<Params_t::count>{});
}
virtual int execute(Types ... t){
std::cout << " default ";
return 0;
}
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
virtual int execute(int b) override {
BaseA::execute(b);
std::cout << " sub-1 has int " << b << '\n';
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, std::string> {
public:
virtual int execute(int b, std::string c) override {
BaseA::execute(b, c);
std::cout << " sub-2 is int: "<<b<<" and str: " << c;
return 0;
}
};
// SubA3 may has other arguments
int main() {
std::vector<BaseAA *> as(3);
as[0] = new SubA1();
as[1] = new SubA2();
as[0]->execute(Params(std::make_tuple(1)));
as[1]->execute(Params(std::make_tuple(1, "2"s))); // s makes std::string
// as[2] ...
return 0;
}
https://godbolt.org/z/tueU2f
When you create a
vector<BaseA<> *> as(2);
you are expecting that vector can accept any type. Which is, I believe, wrong in C++. The vector can accept only type.
When you use template to instantiate the Base class type, the compiler will generate following class hierarchy for you.
class BaseA_int {
public:
virtual int execute(int) = 0;
};
// subclass 1
class SubA1 :public BaseA_int {
public:
int execute(int b) override {
//...
return 0;
}
};
class BaseA_int_string
{
public:
virtual int execute(int, string) = 0;
};
// subclass 2
class SubA2 :public BaseA_int_string {
int execute(int b, string c) override {
//...
return 0;
}
};
And here you can see that derived classes uses different base classes. As the vector can only one type, Base<> *, but your are assigning a type of Base to it, the compiler gives an error.
So Base and Base are entirely two different base classes.
The below will compile without any issue, but it cannot accept Base
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// template base class A
template <typename ... Types>
class BaseA {
public:
virtual int execute(Types ...) = 0;
};
// subclass 1
class SubA1 :public BaseA<int> {
int execute(int b) override {
//...
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, string> {
int execute(int b, string c) override {
//...
return 0;
}
};
int main() {
vector<BaseA<int> *> as(2);
as[0] = (BaseA<int> *) new SubA1(); // type conversion error here
as[0]->execute(1);
return 0;
}

How the base class calls the closure passed by the derived class in c++?

I have a base class, and it have a member function that sometime will be called. Usually, this function have a parameter that pointing to itself.
class Base {
public:
std::function<bool(Base *, int)> foo;
private:
int x{};
public:
static std::shared_ptr<Base> create() {
return std::make_shared<Base>();
}
Base() = default;
const std::function<bool(Base *, int)> &getFoo() const {
return foo;
}
void setFoo(const std::function<bool(Base *, int)> &foo) {
Base::foo = foo;
}
int getX() const {
return x;
}
void setX(int x) {
Base::x = x;
}
};
But when I have a derived class, how can I set this member function? Although the base class pointer can point to a subclass object, but I directly passed into the derived object, the compiler does not pass.
class Derived : public Base {
public:
static std::shared_ptr<Derived> create() {
return std::make_shared<Derived>();
}
};
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Derived *derived, int x) -> bool { return derived->getX() > x; });
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}
error: no viable conversion from '(lambda at
main.cpp:62:15)' to 'const
std::function'
b->setFoo([](Derived *derived, int x) -> bool { return derived->getX() > x; });
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
So, is there any good idea to pass a closure to base class, and base class call it instead of derived class, and the most important thing is that closure have a parameter which is point to who pass the closure!
Note
I am going to assume that for some reason the closure in question needs access to Derived's methods/data members, and the OP's example does not convey that very well. Otherwise, why not just use Base * as the input parameter:
b->setFoo([](Base *derived, int x) -> bool { return derived->getX() > x; });
#user3655463's answer contains the full code for this case.
Simple solution
In case the CRTP solution proposed by #Yuki does not work for you, you could just use Base * as an argument of the closure and static_cast it in the closure body (the compiler can optimize away the cast), like this:
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Base *derived, int x) -> bool {
return static_cast<Derived *>(derived)->getX() > x;
});
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}
Live example.
If you really need the type in the closure to be Derived *
In case having Base * in the closure is not acceptable, you could hide the setFoo method from Base with a special implementation in Derived which will do the cast for you:
class Derived : public Base {
public:
static std::shared_ptr<Derived> create() {
return std::make_shared<Derived>();
}
template <typename Closure>
void setFoo(Closure foo) {
Base::setFoo([foo](Base *base, int x) {
return foo(static_cast<Derived *>(base), x);
});
}
};
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Derived *derived, int x) -> bool {
return derived->getX() > x;
});
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}
This allows you to use the same interface as you have in your original main funciton.
Live example.
If you have a lot of derived classes, and don't want to hide that method over and over again in each class
Now things get a bit complicated, and note that it's a good chance doing something like this would be overengineering in your case, but I just want to demonstrate that it can be done - here is where CRTP comes into play. It is used to implement a mixin which provides an implementation of the setFoo method:
template <typename ConcreteDerived, typename DirectBase>
class EnableSetFooAndInherit : public DirectBase {
public:
template <typename Closure>
void setFoo(Closure foo) {
DirectBase::setFoo([foo](DirectBase *base, int x) {
return foo(static_cast<ConcreteDerived *>(base), x);
});
}
};
class Derived : public EnableSetFooAndInherit<Derived, Base> {
public:
static std::shared_ptr<Derived> create() {
return std::make_shared<Derived>();
}
};
class Derived2 : public EnableSetFooAndInherit<Derived2, Base> {
public:
static std::shared_ptr<Derived2> create() {
return std::make_shared<Derived2>();
}
};
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Derived *derived, int x) -> bool {
return derived->getX() > x;
});
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
auto d2 = Derived2::create();
d2->setX(77);
d2->setFoo([](Derived2 *derived, int x) -> bool {
return derived->getX() < x;
});
if (d2->getFoo()) {
auto res = d2->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}
Live example.
If a template base solution fits your style then this might work.
template <typename D>
class Base {
public:
std::function<bool(D*, int)> foo;
private:
int x{};
public:
static std::shared_ptr<Base> create() { return std::make_shared<Base>(); }
Base() = default;
const std::function<bool(D*, int)>& getFoo() const { return foo; }
void setFoo(const std::function<bool(D*, int)>& foo) { Base::foo = foo; }
int getX() const { return x; }
void setX(int x) { Base::x = x; }
};
class Derived : public Base<Derived> {
public:
static std::shared_ptr<Derived> create() { return std::make_shared<Derived>(); }
};
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Derived* derived, int x) -> bool { return derived->getX() > x; });
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}
Can't you just use Base (just as you designed):
d->setFoo([](Base* derived, int x) -> bool { return derived->getX() > x; });
Whole code:
#include <algorithm>
#include <iostream>
#include <vector>
#include <functional>
#include <memory>
class Base {
public:
std::function<bool(Base *, int)> foo;
private:
int x{};
public:
static std::shared_ptr<Base> create() {
return std::make_shared<Base>();
}
Base() = default;
const std::function<bool(Base *, int)> &getFoo() const {
return foo;
}
void setFoo(const std::function<bool(Base *, int)> &foo) {
Base::foo = foo;
}
int getX() const {
return x;
}
void setX(int x) {
Base::x = x;
}
};
class Derived : public Base {
public:
static std::shared_ptr<Derived> create() {
return std::make_shared<Derived>();
}
};
int main() {
auto d = Derived::create();
d->setX(77);
d->setFoo([](Base* derived, int x) -> bool { return derived->getX() > x; });
if (d->getFoo()) {
auto res = d->foo(d.get(), 99);
std::cout << res << std::endl;
}
return 0;
}

Friend Function calling Static Members of Derived Classes. Not getting expected output

My first post here :)
I am having a problem with the following C++ code. I have an ABC class A, and two derived classes B and C. All of them have a static member called id:
using std::cout;
class A
{
private:
friend int bar(A& a);
static const int id = 1;
virtual void foo() = 0;
};
class B : public A
{
private :
friend int bar(A& a);
static const int id = 2;
void foo() { /*Do something*/ }
};
class C : public A
{
private:
friend int bar(A& a);
static const int id = 3;
void foo() { /*Do something*/ }
};
int bar(A& a)
{
return a.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
I was expecting this code to print out 2 and 3 - rather it prints out 1 and 1 (bar() is always using A::id). What am I doing wrong? Any ideas?
Based on the comments below, this the final code I am using. It works, but would love to hear more thoughts :)
#include <iostream>
using std::cout;
class A
{
private:
virtual void foo() = 0;
};
class B : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 2;
void foo() { /*do something*/ }
};
class C : public A
{
private:
template <typename T>
friend int bar(T& t);
static const int id = 3;
void foo() { /*do something*/ }
};
template <typename T>
int bar(T& t)
{
return t.id;
}
int main()
{
B b;
C c;
cout << bar(b) << "\n";
cout << bar(c) << "\n";
return 0;
}
a.id will be defined at compile-time as A::id. You would need to define a virtual member (non-static) function in class A and have it overridden in B and C to return their respective ids and call this function in bar.
Is there any way to avoid writing int foo() { return id; } for all the derived classes?
Yes, using templates. For example:
template <typename T>
int foo (T& x)
{
return x.id;
}
However, if id is private, this doesn't reduce the code by all that much.

Property like features in C++?

My use is pretty complicated. I have a bunch of objs and they are all passed around by ptr (not reference or value unless its an enum which is byval). At a specific point in time i like to call CheckMembers() which will check if each member has been set or is null. By default i cant make it all null because i wouldnt know if i set it to null or if it is still null bc i havent touch it since the ctor.
To assign a variable i still need the syntax to be the normal var = p; var->member = new Type;. I generate all the classes/members. So my question is how can i implement a property like feature where i can detect if the value has been set or left as the default?
I am thinking maybe i can use C++ with CLR/.NET http://msdn.microsoft.com/en-us/library/z974bes2.aspx but i never used it before and have no idea how well it will work and what might break in my C++ prj (it uses rtti, templates, etc).
Reality (edit): this proved to be tricky, but the following code should handle your requirements. It uses a simple counter in the base class. The counter is incremented once for every property you wish to track, and then decremented once for every property that is set. The checkMembers() function only has to verify that the counter is equal to zero. As a bonus, you could potentially report how many members were not initialized.
#include <iostream>
using namespace std;
class PropertyBase
{
public:
int * counter;
bool is_set;
};
template <typename T>
class Property : public PropertyBase
{
public:
T* ptr;
T* operator=(T* src)
{
ptr = src;
if (!is_set) { (*counter)--; is_set = true; }
return ptr;
}
T* operator->() { return ptr; }
~Property() { delete ptr; }
};
class Base
{
private:
int counter;
protected:
void TrackProperty(PropertyBase& p)
{
p.counter = &counter;
counter++;
}
public:
bool checkMembers() { return (counter == 0); }
};
class OtherObject : public Base { }; // just as an example
class MyObject : public Base
{
public:
Property<OtherObject> x;
Property<OtherObject> y;
MyObject();
};
MyObject::MyObject()
{
TrackProperty(x);
TrackProperty(y);
}
int main(int argc, char * argv[])
{
MyObject * object1 = new MyObject();
MyObject * object2 = new MyObject();
object1->x = new OtherObject();
object1->y = new OtherObject();
cout << object1->checkMembers() << endl; // true
cout << object2->checkMembers() << endl; // false
delete object1;
delete object2;
return 0;
}
There are a number of ways to do this, with varying tradeoffs in terms of space overhead. For example, here's one option:
#include <iostream>
template<typename T, typename OuterClass>
class Property
{
public:
typedef void (OuterClass::*setter)(const T &value);
typedef T &value_type;
typedef const T &const_type;
private:
setter set_;
T &ref_;
OuterClass *parent_;
public:
operator value_type() { return ref_; }
operator const_type() const { return ref_; }
Property<T, OuterClass> &operator=(const T &value)
{
(parent_->*set_)(value);
return *this;
}
Property(T &ref, OuterClass *parent, setter setfunc)
: set_(setfunc), ref_(ref), parent_(parent)
{ }
};
struct demo {
private:
int val_p;
void set_val(const int &newval) {
std::cout << "New value: " << newval << std::endl;
val_p = newval;
}
public:
Property<int, demo> val;
demo()
: val(val_p, this, &demo::set_val)
{ }
};
int main() {
demo d;
d.val = 42;
std::cout << "Value is: " << d.val << std::endl;
return 0;
}
It's possible to get less overhead (this has up to 4 * sizeof(void*) bytes overhead) using template accessors - here's another example:
#include <iostream>
template<typename T, typename ParentType, typename AccessTraits>
class Property
{
private:
ParentType *get_parent()
{
return (ParentType *)((char *)this - AccessTraits::get_offset());
}
public:
operator T &() { return AccessTraits::get(get_parent()); }
operator T() { return AccessTraits::get(get_parent()); }
operator const T &() { return AccessTraits::get(get_parent()); }
Property &operator =(const T &value) {
AccessTraits::set(get_parent(), value);
return *this;
}
};
#define DECL_PROPERTY(ClassName, ValueType, MemberName, TraitsName) \
struct MemberName##__Detail : public TraitsName { \
static ptrdiff_t get_offset() { return offsetof(ClassName, MemberName); }; \
}; \
Property<ValueType, ClassName, MemberName##__Detail> MemberName;
struct demo {
private:
int val_;
struct AccessTraits {
static int get(demo *parent) {
return parent->val_;
}
static void set(demo *parent, int newval) {
std::cout << "New value: " << newval << std::endl;
parent->val_ = newval;
}
};
public:
DECL_PROPERTY(demo, int, val, AccessTraits)
demo()
{ val_ = 0; }
};
int main() {
demo d;
d.val = 42;
std::cout << "Value is: " << (int)d.val << std::endl;
return 0;
}
This only consumes one byte for the property struct itself; however, it relies on unportable offsetof() behavior (you're not technically allowed to use it on non-POD structures). For a more portable approach, you could stash just the this pointer of the parent class in a member variable.
Note that both classes are just barely enough to demonstrate the technique - you'll want to overload operator* and operator->, etc, as well.
Here's my temporary alternative. One that doesn't ask for constructor parameters.
#include <iostream>
#include <cassert>
using namespace std;
template <class T>
class Property
{
bool isSet;
T v;
Property(Property&p) { }
public:
Property() { isSet=0; }
T operator=(T src) { v = src; isSet = 1; return v; }
operator T() const { assert(isSet); return v; }
bool is_set() { return isSet; }
};
class SomeType {};
enum SomeType2 { none, a, b};
class MyObject
{
public:
Property<SomeType*> x;
Property<SomeType2> y;
//This should be generated. //Consider generating ((T)x)->checkMembers() when type is a pointer
bool checkMembers() { return x.is_set() && y.is_set(); }
};
int main(int argc, char * argv[])
{
MyObject* p = new MyObject();
p->x = new SomeType;
cout << p->checkMembers() << endl; // false
p->y = a;
cout << p->checkMembers() << endl; // true
delete p->x;
delete p;
}