Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функторы в шаблонах. Код работает - но не должен. Шаблонная реализация класса свойств  
:(
    Опции темы
AndrewWK
Дата 14.9.2015, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 14.9.2015

Репутация: нет
Всего: нет



Здравствуйте!
Хочу написать реализацию класса свойства на шаблоне. Рабочий код:
Код

#include "stdafx.h"

struct IsEnabled
{
    bool operator()(void) { return true;}
};

struct IsVisible
{
    bool operator()(void) { return true;}
};

template<typename ClassName, bool (ClassName::*enabler)()>
struct Enabler
{
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*enabler)();}
};

template<typename ClassName,typename Type, Type (ClassName::*getter)()>
struct Getter
{
    ClassName * m_sender;
    Type operator()(){ return ((*m_sender).*getter)();}
};

template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
};

template<typename GetterFunctor, typename SetterFunctor,typename EnableFunctor = IsEnabled, typename VisibleFunctor = IsVisible>
class CProperty
{
    
public:
    GetterFunctor m_getter;
    SetterFunctor m_setter;
    EnableFunctor m_enabler;
    VisibleFunctor m_visible;

    bool getValue()
    {
        return m_getter();
    }
    void setValue(bool  val)
    {
        m_setter(val);
    }

    bool isEnabled()
    {
        return m_enabler();
    }

    bool isVisible()
    {
        return m_visible();
    }
};



class test
{
public:

    test()
    {
    }
    void initProps()
    {
        CProperty<Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>> prop;
        prop.getValue();
        prop.isEnabled();
        prop.isVisible();
        prop.setValue(false);
    }
    
    bool getVal()
    {
        return true;
    }
    void setVal(bool b)
    {
    }
    bool enabler()
    {
        return true;
    }
    bool visible()
    {
        return true;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    test s;
    s.initProps();
    return 0;
}



Как видно свойство опрашивает заданный функтор - getter, setter и т.д, а использование функторов позволяет сделать не всегда необходимые методы проверки свойства - редактируемо, видимо  - методами по дефолту.  Но, этот код работает, хотя в каждом функторе в дебаге m_sender= 0xCCCCCC - память неинициализированна. Следовательно вызов в функторе, например, Setter - ((*m_sender).*setter)(val); должно приводить к падению. Оптимизация выключена в опциях компилятора.  Почему работает?  smile 
PM MAIL   Вверх
xvr
Дата 14.9.2015, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Работает потому что неинициализированный m_sender передается в ваш setter (test::setVal) как this (и действительно в виде мусора). Но сам test::setVal this никак не использует, поэтому и не падает

PM MAIL   Вверх
AndrewWK
Дата 14.9.2015, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 14.9.2015

Репутация: нет
Всего: нет



А этот код  безопасен? Вообще,  можете подсказать - у меня правильная реализация - или нужно что-то подправить? 
А то у меня большие сомнения на этот счет. Допустим я изменю в функторе Setter:
Код

template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    Setter(ClassName * name):m_sender(name){}  //добавил конструктор
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
};


И добавлю в CProperty конструктор
Код

CProperty():m_setter(this)
{

}


При компиляции падает Microsoft c/c++ Optimizing Compiler - что наводит на мысль, что сделано не так.
PM MAIL   Вверх
xvr
Дата 14.9.2015, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(AndrewWK @  14.9.2015,  15:47 Найти цитируемый пост)
Допустим я изменю в функторе Setter:

Это правильная реализация

Цитата(AndrewWK @  14.9.2015,  15:47 Найти цитируемый пост)
При компиляции падает Microsoft c/c++ Optimizing Compiler - что наводит на мысль, что сделано не так. 

Не должен падать. Покажите законченный пример (на котором падает) - возможно что то не учли, а может бага в компилаторе  smile 

PM MAIL   Вверх
AndrewWK
Дата 14.9.2015, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 14.9.2015

Репутация: нет
Всего: нет



Цитата(xvr @  14.9.2015,  16:04 Найти цитируемый пост)
Это правильная реализация
   - правильная всмысле теперь, когда я добавил инициацию m_sender  в конструкторе функтора?

Полный код тот же самый + изменения в функторах - добавлен конструктор, даже в тех, что должны вызываться по умолчанию. ( среда VS 2008 , машина Win8.1 x64, тестовое приложение 32 bit) - 
Код


// sdsd.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


//Вызываются по-дефолту, если enabler и/или visible функтор не указаны 
template<typename ClassName>
struct IsEnabled
{
    ClassName *m_sender;
    IsEnabled(ClassName * name):m_sender(name){}
    bool operator()(void) { return true;}
};

template<typename ClassName>
struct IsVisible
{
    ClassName *m_sender;
    IsVisible(ClassName * name):m_sender(name){}
    bool operator()(void) { return true;}
};




template<typename ClassName, bool (ClassName::*enabler)()>
struct Enabler
{
    Enabler(ClassName * name){m_sender = name;}
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*enabler)();}
};

template<typename ClassName, bool (ClassName::*visible)()>
struct Visible
{
    Visible(ClassName * name):m_sender(name){}
    ClassName *m_sender;
    bool operator()(void) { return ((*m_sender).*visible)();}
};


template<typename ClassName,typename Type, Type (ClassName::*getter)()>
struct Getter
{
    Getter(ClassName * name):m_sender(name){}
    ClassName * m_sender;
    Type operator()(){ return ((*m_sender).*getter)();}
};

template<typename ClassName,typename Type,void (ClassName::*setter)(Type )>
struct Setter
{
    Setter(ClassName * name):m_sender(name){}
    ClassName *m_sender;
    void operator ()(Type val)
    { 
        ((*m_sender).*setter)(val);
    }
    Type m_val;
};

template<typename ClassName,typename GetterFunctor, typename SetterFunctor,typename EnableFunctor = IsEnabled<ClassName>, typename VisibleFunctor = IsVisible<ClassName>>
class CProperty
{
    
public:
    GetterFunctor m_getter;
    SetterFunctor m_setter;
    EnableFunctor m_enabler;
    VisibleFunctor m_visible;

    CProperty():m_setter(this),m_getter(this),m_enabler(this),m_visible(this)
    {

    }

    bool getValue()
    {
        return m_getter();
    }
    void setValue(bool  val)
    {
        m_setter(val);
    }

    bool isEnabled()
    {
        return m_enabler();
    }

    bool isVisible()
    {
        return m_visible();
    }
};



class test
{
public:

    test()
    {
    }
    void initProps()
    {
        CProperty<test,Getter<test,bool,&test::getVal>,Setter<test,bool,&test::setVal>,Enabler<test,&test::enabler>,Visible<test,&test::visible>> prop;
        prop.getValue();
        prop.isEnabled();
        prop.isVisible();
        prop.setValue(false);
    }
    
    bool getVal()
    {
        return true;
    }
    void setVal(bool b)
    {
    }
    bool enabler()
    {
        return true;
    }
    bool visible()
    {
        return true;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    test s;
    s.initProps();
    return 0;
}



Если закоментировать все конструкторы и убрать инициализацию из CProperty конструктора, тогда все ок, а иначе падает оптимизатор.

PM MAIL   Вверх
borisbn
Дата 14.9.2015, 19:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



У тебя в CProperty в качестве второго параметра ( GetterFunctor ) передаётся
Цитата
Getter<test,bool,&test::getVal>

А в конструкторе CProperty ему скрамливается this (aka CProperty*).
Цитата
CProperty():m_setter(this),m_getter(this),m_enabler(this),m_visible(this)

Ты уж определись, кто будет владеть геттерами и сеттерами - test или CProperty

Это сообщение отредактировал(а) borisbn - 14.9.2015, 19:25


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
volatile
Дата 14.9.2015, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(AndrewWK @ 14.9.2015,  15:47)
И добавлю в CProperty конструктор
Код

CProperty():m_setter(this)
{

}


При компиляции падает Microsoft c/c++ Optimizing Compiler - что наводит на мысль, что сделано не так.

m_setter'у нужен не указатель на CProperty, а указатель на ваш test
Код

CProperty(ClassName * p):m_setter(p),
{

}

ну и инициализировать его соответственно.

Добавлено через 1 минуту и 5 секунд
пока писал, borisbn, опередил  smile 

PM MAIL   Вверх
xvr
Дата 14.9.2015, 19:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(AndrewWK @  14.9.2015,  16:23 Найти цитируемый пост)
   - правильная всмысле теперь, когда я добавил инициацию m_sender  в конструкторе функтора?

Да

PS. По падению уже ответили  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1191 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.