Могу ли я объединить эти два класса через специализацию? - PullRequest
0 голосов
/ 08 февраля 2012

Вот класс, который я написал для проверки свойств .NET.Похоже, делать то, что я хочу.Однако вместо использования Property1 и Property2 я могу написать Property и выяснить, какой из двух классов мне нужен?

#include <cstdio>

template <class T>
class Property{
protected:
    Property(const Property&p) {}
    Property() {}
public:
    virtual Property& operator=(const Property& src)=0;
    virtual Property& operator=(const T& src)=0;
    virtual operator T() const=0;
};

template <class T>
class Property1 : public Property<T> {
    T v;
public:
    Property1(const Property1&p) {*this=static_cast<T>(p);}
    //Property1() { printf("ctor %X\n", this);}
    Property1(){}
    Property& operator=(const Property& src) { return*this=static_cast<T>(src); }
    Property& operator=(const T& src) {
        printf("write %X\n", this);
        v = src; 
        return *this; 
    }
    operator T() const {
        printf("Read %X\n", this);
        return v;
    }
};

template <class T>
class Property2 : public Property<T> {
    typedef T(*Gfn)();
    typedef void(*Sfn)(T);
    Gfn gfn;
    Sfn sfn;
public:
    Property2(const Property2&p) {*this=static_cast<T>(p);}
    //Property2() { printf("ctor %X\n", this);}
    Property2(Gfn gfn_, Sfn sfn_):gfn(gfn_), sfn(sfn_) {}
    Property& operator=(const Property& src) { return*this=static_cast<T>(src); }
    Property& operator=(const T& src) {
        printf("write %X\n", this);
        sfn(src);
        return *this; 
    }
    operator T() const {
        printf("Read %X\n", this);
        return gfn();
    }
};

void set(int v) {}
int get() {return 9;}

Property1<int> a, b;
Property2<int> c(get,set), d(get,set);
void fn(Property<int>& v) { v=v=31; }
int main(){
    a=b=5;
    c=d=11;
    a=c=b=d=15;
    fn(a);
    fn(c);
}

Ответы [ 2 ]

2 голосов
/ 08 февраля 2012

Вы можете заставить Property удерживать и работать с реализацией, разрешить Property1 и Property2 быть двумя такими реализациями и определить, какую из двух создать с помощью ctor Property:

template<typename T>
class PropertyInterface {
public:
    virtual ~PropertyInterface() {}
    virtual T get() const = 0;
    virtual void set(const T&) = 0;
};

template<typename T>
class Property1 : public PropertyInterface<T> {
    T v;
public:
    T get() { return v; }
    void set(const T& value) { v = value; }
};

template<typename T>
class Property2 : public PropertyInterface<T> {
    Gfn g;
    Sfn s;
public:
    Property2(Gfn getter, Sfn setter) : g(getter), s(setter) {}

    T get() { return g(); }
    void set(const T& v) { set(v); }
};

template<typename T>
class Property {
    PropertyInterface<T> impl;
public:
    Property() : impl(new Property1()) {}
    Property(const T& v) : impl(new Property1()) { impl->set(v); }
    Property(Gfn getter, Sfn setter) : impl(new Property2(getter, setter)) {}
    Property(const Property& p) : impl(new Property1()) { impl->set(p.impl->get()); }
    // ...more ctors...

    ~Property() { delete impl; }

    Property& operator=(const Property&) { impl->set(p.impl->get()); return *this; }
    Property& operator=(const T& v) { impl->set(v); return *this; }

    operator T() const { return impl->get(); }
 };
0 голосов
/ 08 февраля 2012

Разве это не то, что должна делать фабрика?

Фабричный метод также может быть помещен в класс свойств.Я предпочитаю создавать дополнительный фабричный класс, чтобы было ясно, что он использует фабричный шаблон.

Редактировать: Добавлена ​​перегрузка фабричного метода

template <class T>
class Property {
};

template <class T>
class Property1 : public Property<T> {
};

template <class T>
class Property2 : public Property<T> {
public:
    typedef T(*Gfn)();
    typedef void(*Sfn)(T);
    Property2(Gfn, Sfn) {}

};

class PropertyFactory {
public:
    template<class T>
    static Property<T>* InstanciateProperty() {
        return new Property1<T>();
    }
    template<class T>
    static Property<T>* InstanciateProperty(typename Property2<T>::Gfn gfn, typename Property2<T>::Sfn sfn) {
        return new Property2<T>(gfn, sfn);
    }
};

void set(int){}
int get() { return 0; }

int main(int argc, char *argv[])
{
    Property<int>* prop(PropertyFactory::InstanciateProperty<int>());
    Property<int>* prop1(PropertyFactory::InstanciateProperty<int>(&get, &set));
    delete prop;
    delete prop1;
    return 0;
}
...