Здравствуйте, Atomic Max, Вы писали:
AM>Но я озадачился другим. Можно ли не хранить вообще никаких дополнительных указателей?
//----------------------------------------------------------------------
//да, property без изменения бинарной раскладки класса
//вызов через указатель на член убивает оптимизирующий компилятор.
//VS2003 распознает эти property в IntelliSense
//сразу возникает вопрос, как разрулить это -
//T Owner::GetX() const
//T Owner::GetX() const volatile
//T Owner::GetX() volatile
//Owner::x
//T Owner::GetX()
//T &Owner::GetX()
//мне кажется, что это можно сделать через
//sizeof(overloaded_function(MakeT())) трюк, но мне лень это проверять
//тут еще подводные камни с константностью функции NAME(),
//без парочки const_cast видимо не обойдется, если доводить до ума.
template <
class Owner,
class PropT,
void (Owner::*Setter)(PropT),
PropT (Owner::*Getter)()>
struct Property
{
Owner &owner;
Property(Owner &owner): owner(owner) {};
//да, void. Не хочу мозг парить.
void operator =(const PropT &x) { (owner .* Setter)(x); }
operator const PropT () { return (owner .* Getter)(); }
};
//можно сделать PROPERTY_RW, PROPERTY_R, PROPERTY_W,
#define PROPERTY(NAME, Owner, T, Setter, Getter)\
Property<Owner, T, &Owner::Setter, &Owner::Getter> NAME() \
{ \
return Property<Owner, T, &Owner::Setter, &Owner::Getter>(*this);\
}
//----------------------------------------------------------------------
#include <fstream>
#include <iostream>
#include <string>
struct MegaClass
{
private:
int GetFromFile()
{
int i;
std::ifstream f("config.txt");
f >> i;
return i*2;
}
void SetValueInFile(int i)
{
std::ofstream f("config.txt");
f << i;
}
std::string GetS() { return "hello"; }
void SetS(std::string sss) { std::cout <<sss; }
public:
PROPERTY(X, MegaClass, int, SetValueInFile, GetFromFile);
PROPERTY(Y, MegaClass, int, SetValueInFile, GetFromFile);
PROPERTY(Sss, MegaClass, std::string, SetS, GetS);
MegaClass()
{
this->X() = 0;
}
};
volatile int i;
class Test2
{
private:
void SetI(int i) { ::i = i; }
int GetI() { return ::i; }
public:
PROPERTY(I, Test2, int, SetI, GetI);
};
int main()
{
std::cout <<sizeof(MegaClass) <<"\n"; //empty class
MegaClass mc;
mc.X() = 10;
int i = mc.Y();
std::string s = mc.Sss();
mc.Sss() = "world";
//проверяю в листинге на asm, что компилятор уничтожает лишние вызовы.
Test2 t;
t.I() = 10;
i = t.I();
std::cout <<i;
}