C++元编程思想(译)

C++ 是一种类型概念较强的语言,编译的时候都需要知道变量的类型。有时,在编译过程中,需要动态确定类型

先看一种简单的 商品信息 的存储结构;


示例code:

    class Book
    {
    public:
        Book(const string & author_,
             const string & title_,
             const string & publisher_,
             double price_,
             double weight_);
        string getName()
        {
            string name;
            name = author + ": " + title;
            return name.substr(0, 40);
        }
        double getPrice();
        double getWeight();
    private:
        string author, title, publisher;
        double price, weight;
    };


还可以继续扩展开来,如果有新的类似商品,这样扩展


但是对于如果业务扩张,继续销售T 恤,因为接口不能再如 getweight() 等这样了,所以就无法扩展了。


MetaClass 

可以获取类型和对象的信息,并创建新的类型,类型属性,类型实例等。 MOP

关于对象的属性,结构,等就是meta 信息。  MOP就是封装 meta- level 和 object-level 。


操作主要包括:

定义个新的类型 / 添加类型的属性 / 查询类型属性/  创建对象 / 查询对象的类型 / 设置对象的属性 / 查询对象的属性 / 删除对象




Type是为了区分出不同的属性,使用枚举变量来区分。因为有不同的value, 所以我们定义一个basevalue

calss Type
{
  public:
      enum Type T{stringT , int T, double T, unknown T};
       explicit Type(Type T typeId_): typeId(typeId_){}
      BaseValue * newValue() const
{
   return prototypes[typeId]->clone();
}
 TypeT getType() const
{
   return typeId;
}
static void int();
{
   prototypes[stringT] = new Value<string>("");
   prototypes[intT] = new Value<int>(0);
   prototypes[double T] = new Value<double>(0);
}
private:
   TypeT typeId;
   static vector<BaseValue *>prototypes;
}
vector<BaseValue*>Type::prototypes(Type::unknownT);

通过类型创建新的value, 属性attribute 为了获取类型的名称和类型

class Attribute
{
   public:
     Attibute(const string &name_, Type:: TypeT typeId)
    :name(name_),type_(typeID)
    {}
    const string & getName() const
 {
     return name; 
 }
    Type getType() const
 {
   return type_;
}
private:
  string name;
  Type type_;
};

继承的attributes 放在首位

class的主要目的就是为了创建新的对象,所以有 newObject() 返回一个指针指向对象。对于所有创建的对象,需要保存引用;如果有新的添加的属性,禁止添加到已经有实例的类中;其他方法会比较麻烦。为对象和类型维持属性列表。 属性是仅仅自己,还是包含继承该类的其他属性。对于单独的对象来说,如果可以访问到完整的属性列表是更好的。确保对于不同的类,知道它们的属性findAttribute() 搜索到属性,并返回一个引用index而 getarrtibute() 则通过index 返回相应的value。 最后的问题是什么时间添加属性: 在类的定义时候或者稍后些

class ClassDef
{   //typedefs Container, Iterator for attributes
  public:
   ClassDef(ClassDef const *base, const string &name_)
   :baseClass(base), name(name_),
    definitionFix(false)
{
   baseInit();
   effectiveAttributes.insert(effectiveAttributes.end(),
                                         ownAttibutes.begin(),
                                         ownAttributes.end());
}
template<typename iterator>
ClassDef(ClassDef const * base, const string name_, iterator attribBegin, iterator attibEnd)
  : baseClass(base), name(name_),
  ownAttributes(attriBegin, attribEnd),
  definitionFix(false)
{
   baseInit();
   effectiveAttributes.insert(effectiveAttributes.end(),
                                        ownAtttibutes.Begin(),
                                         ownAttributes.end());
}
string getName() const;
Object * newObject() const
{
   definitionFix = true;
   return new Object(this);
}
AtttIterator attribBegin() const;
AttrIterator attriEnd() const;
AttrIterator const & getAttribute(size_t idx) const;
void addAttribute(const Attribute&);
size_t getAttributeCount() const;

size_t findAttribute(string const & name) const
{
   // this does a reverse search to find the most derived
AtrtibuteContainer::const_reverse_iterator i;

for(i = effectiveAttributes.rbegin();
     i != effectiveArributes.rend();
     ++i)
{
    if(i->getName() = name)
    {
       return distance(i, effectiveAttributes.rend()) - 1;
    }
}
return getAttributeCount();
}
private:
  void baseInit()
 {
   if(baseClass)
   {
      baseClass->definitionFix = true;
      copy(baseClass->attribBegin(), baseClass->attribEnd(), back_inserter<AttributeContainer>(effectiveAttributes));
    }
}
ClassDef const * const baseClass;
string name;
AttributeContainer ownAttributes, effectiveAttributes;
mutable bool definitionFix;
}

传递的是值,传递handle 来实现值的传递


Value BaseValue::get()
{
   return *this;  // call Value(BaseValue const &)
}

class BaseValue
{
   public:
    virtual ~BaseValue() {}
    virtual BaseValue * clone() const = 0;
    virtual string asString() const = 0;
    // fromString()
   
    virtual void set(Value const &v) = 0;
   // no get()!

private:
   //Type info
};
需要有 int, double, strring 等类型, 这种很容易让人想到使用模板

    template <typename PlainT>
    class RealValue : public BaseValue
    {
    public:
        RealValue(PlainT v)
         : val(v) {}

        RealValue * clone() const
        {
            return new RealValue(*this);
        }

        string asString() const
        {
            ostringstream os;
            os << val;
            return os.str();
        }

        operator PlainT() const // conversion to plain type
        {
            return val;
        }

        RealValue<PlainT>::set(Value const & v)
        {
            val = v.get<PlainT>();
        }

    private:
        PlainT val;
    };

主要的事情就是 删除/创建,

    class Value        // Value handle
    {
    public:
        Value(BaseValue const & bv)
         : v(bv.clone())
        {}

        Value(Value const & rhs)
         : v(rhs.v ? rhs.v->clone() : 0)
        {}

        explicit Value(BaseValue * bv = 0)
         : v(bv)
        {}

        ~Value()
        {
            delete v;
        }

        Value & operator=(const Value & rhs)
        {
            // this is not a typical pimpl assignment, but a set()
            if (v)
            {
                if (rhs.v)
                { // fine, all v's exist
                    v->set(rhs);
                }
                else
                { // the other v doesn't exist, so we must delete our own :-(
                    BaseValue * old = v;
                    v = 0;
                    delete old;
                }
            }
            else
            { // we don't have a v, so just copy the other
                v = (rhs.v ? rhs.v->clone() : 0);
            }

            return *this;
        }

        template <typename PlainT>
        PlainT get() const
        {
            if (v)
            {
                RealValue<PlainT> const & rv
                    = dynamic_cast<RealValue<PlainT> const &>(*v);
                return rv;        // uses conversion operator
            }
            else
            {
                return PlainT();
            }
        }

        std::string asString() const
        {
            if (v)
            {
                return v->asString();
            }
            else
            {
                return string();
            }
        }

    private:
        BaseValue * v;
    };

实体对象

  class Object
    {
    public:
        explicit Object(ClassDef const * class_)
         : myClass(class_), values(class_->getAttributeCount())
        {
            buildValueList();
        }

        ClassDef const & instanceOf() const
        {
            return *myClass;
        }

        Value getValue(size_t attribIdx) const
        {
            return *values[attribIdx]; // calls Value(BaseValue &)
        }
        Value getValue(string const & attribName) const
        {
            size_t idx = instanceOf()->findAttribute(attribName);
            // should check for not found
            return getValue(idx);
        }

        void setValue(size_t idx, Value const & v)
        {
            values[idx]->set(v);
        }
        void setValue(string const & attribName, Value const &v)
        {
            size_t idx = instanceOf()->findAttribute(attribName);
            // should check for not found
            setValue(idx, v);
        }

    private:
        typedef vector<BaseValue *> ValueContainer;
        void buildValueList()
        {
            ClassDef::AttrIterator a;
            ValueContainer::iterator i = values.begin();
            for (a = instanceOf()->attribBegin();
                 a != instanceOf()->attribEnd();
                 ++a, ++i)
            {
                *i = a->getType().newValue();
            }
        }

        ClassDef const * const myClass;
        ValueContainer values;
    };

应用

创建 book 类型

    ClassDef base(0, "Product", 0,
                  Product::ownAttribBegin(),
                  Product::ownAttribEnd());
    ClassDef book(makeClass<Book>(&base, "Book"));

给book 类型添加属性值

    Object * ecpp(book.newObject());

    ecpp->setValue(5, RealValue<double>(22.50));
    ecpp->setValue(0, RealValue<int>(23456));
    ecpp->setValue(2, RealValue<string>("Scott Meyers"));
    ecpp->setValue("Title", RealValue<string>("Effective C++"));
    ecpp->setValue(6, RealValue<double>(280));
    size_t idx;

    cout << "ecpp:" << endl;
    for (a = book.attribBegin(), idx = 0;
         a != book.attribEnd();
         ++a, ++idx)
    {
        cout << a->getName() << ": "
             << ecpp->getValue(idx).asString() << endl;
    }

    cout << ecpp->getValue("Author").asString() << endl;


原文链接: vollmann.com/en/pubs/meta/meta/meta.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不负初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值