Re[2]: мысль
От: _Winnie Россия C++.freerun
Дата: 18.02.05 04:19
Оценка: 2 (1) +1
Здравствуйте, 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;
}
Правильно работающая программа — просто частный случай Undefined Behavior
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.