Некоторые проблемы с реализацией свойства на основе указателя на член шаблона C ++ - PullRequest
4 голосов
/ 15 августа 2011

Моей целью было сделать свойства в C ++ как в C # - с нетривиальным поведением set / get. Здесь объект Property содержит ссылки на master of prop и его методы set / get.

Реализация, содержание Property.h:

#include <iostream>

using namespace std;

namespace First {

    template <class Master, class Type>
    struct Property
    {
        Master &master;

        const Type (Master::*&get) () const;
        Type (Master::*&set)(Type value);

        Property
        (
            Master &master, 
            const Type (Master::*get) () const, 
            Type (Master::*set)(Type value)
        ): 
            get(get), 
            set(set), 
            master(master) 
        { }

        operator const Type() const { cout << "inside" << endl; return (master.*get)(); }

        Type operator = (Type value)
        {
            return (master.*set)(value);
        }
    };

    // Test chamber.
    class R
    {
        float x;
        const float getx() const { cout << "returning " << 0 << endl; return 0; }
        float setx(float value) { cout << "setting " << value << " in place of " << x << endl; return x = value; }
    public:
        Property<R, float> X;

        R(): X(*this, &R::getx, &R::setx) { }
    };

}

Я также создал .cpp файл:

#include "Property.h"

using namespace First;

int main()
{
    R r;

    r.X = 10;

    float y = r.X;

}

Программа выполняет шаг «назначить», печатая «настройки от 0 до 10», но при вызове шага «извлекает» происходит ошибка, без разницы, какой код (или вообще нет) внутри «R :: getx ()».

~/Sources$ ./a.out          

setting 10 in place of 0
inside
zsh: segmentation fault  ./a.out

Кажется, что вызов (master. * Get ()) сам по себе вызывает ошибку. Что не так в этом коде?

UPD: проверено, что любой другой вызов функций мастера приводит к segfault, только один вызов (master. * Set) успешен. Кажется, что этот вызов делает недействительным состояние объекта, члена к ptr, самого свойства или фазы Луны.

1 Ответ

6 голосов
/ 15 августа 2011
const Type (Master::*&get) () const;
Type (Master::*&set)(Type value);

Удалить & из приведенных выше определений.Из-за & каждый из них связан с параметрами конструктора, которые не существуют после возврата конструктора.

Также обратите внимание, что, похоже, (master.*set)(value) работает, потому что вам не повезло .Это фактически вызывает неопределенное поведение.Но вам повезло, что очень скоро вы узнаете о проблеме, когда (master.*get)() не сработает, что дает segfault.

Использование:

const Type (Master::*get) () const;
Type (Master::*set)(Type value);

Это должно работать сейчас без проблемэто приведет к копированию адресов в списке инициализации, а не к параметрам!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...