Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > адрес поля структуры в структуре


Автор: borisbn 25.1.2012, 16:20
Здравствуйте.

У меня есть такой функтор
Код

template< class T, class FieldType, FieldType T::*FieldPtr >
struct EqualBy
{
    EqualBy( const FieldType & value ) : m_fieldValue( value ) {}
    bool operator()( const T & r ) const {
        return m_fieldValue == r.*FieldPtr;
    }
    bool operator()( const T * p ) const {
        return m_fieldValue == p->*FieldPtr;
    }
private:
    const FieldType m_fieldValue;
};

я его успешно использую для поиска в контейнерах, состоящих из структур
Код

struct A { int x; };
std::vector< A > v;
typedef EqualBy< A, int, &A::x > EqualByX;
std::vector< A >::iterator found = std::find_if( v.begin(), v.end(),  EqualByX( 42 ) );

http://liveworkspace.org/code/3f8197f05bae31f91d16944cff3303b7

Возникла задача искать в чуть более сложной структуре:
Код

struct A { int x; };
struct B { A a; };
std::vector< B > v;
typedef EqualBy< B, int, /* Вот тут не пойму что писать */ > EqualByX;

http://liveworkspace.org/code/fdb9f3e12a524da931a6dc083f333b7d

Вопрос:
1) Можно ли без переделки функтора это организовать ?
2) Если ответ на 1) положительный, то - как ?

Спасибо.

Автор: mes 25.1.2012, 17:09
Цитата(borisbn @  25.1.2012,  15:20 Найти цитируемый пост)
 Можно ли без переделки функтора это организовать ?

нельзя..

Автор: borisbn 25.1.2012, 17:18
mes, спасибо. жаль. а есть что-нибудь подобное в boost'е, чтобы не городить для этого своего монстра ?

Автор: Result 25.1.2012, 17:23
может посмотреть в сторону traits...

Автор: mes 25.1.2012, 17:26
Цитата(borisbn @  25.1.2012,  16:18 Найти цитируемый пост)
 а есть что-нибудь подобное в boost'е, чтобы не городить для этого своего монстра ? 

bind, тогда и ваш функтор не нужен будет smile

Автор: borisbn 25.1.2012, 17:26
Собственно, монстра понятно как делать
Код

template< class T, class FieldType, class U, U T::*S, FieldType U::*FieldPtr >
struct EqualBy
{
    EqualBy( const FieldType & value ) : m_fieldValue( value ) {}
    bool operator()( const T & r ) const {
        return m_fieldValue == r.*S.*FieldPtr;
    }
    bool operator()( const T * p ) const {
        return m_fieldValue == p->*S->*FieldPtr;
    }
private:
    const FieldType m_fieldValue;
};
typedef EqualBy< B, int, A, &B::a, &A::x > EqualByX;

http://liveworkspace.org/code/9475f7faa2e4a4f007ae5900fc45a915

но... ИМХО, это уж слишком...

Добавлено через 2 минуты и 21 секунду
mes, а не подскажете на моём примере, как при помощи bind это организовать ? А то как с "одномерной" структурой мне понятно, а с "двумерной" - не очень...

Автор: mes 25.1.2012, 18:02
вложенный бинд :
Код

  find_if  ( .. , ..  , boost::bind (&A::x, boost::bind(&B::a, _1)) == 42 );


Автор: borisbn 25.1.2012, 18:16
mes, спасибо.
А можно ещё вопрос в догонку ?
этот оператор ==, который подставляется в find_if в качестве предиката, какой-то переопределённый boost'ом ?

Автор: mes 25.1.2012, 19:03
Цитата(borisbn @  25.1.2012,  17:16 Найти цитируемый пост)
этот оператор ==, ... какой-то переопределённый boost'ом 

да, также как и бинд, возвращает binder от своих аргументов..

Добавлено через 2 минуты и 13 секунд
т.е. сравнение  будет происходить позже, в момен вызова биндера, а не в в момент его определения...

Добавлено через 4 минуты и 18 секунд
вместо == можно прибиндить тот же std::equal, но с оператором нагляднее..

Добавлено через 4 минуты и 49 секунд
в C++11 у бинда, насколько я знаю, эти операторы не переопределены.. 

Автор: borisbn 25.1.2012, 19:17
Ясно. Спасибо.

Автор: mes 25.1.2012, 19:24
Цитата(borisbn @  25.1.2012,  18:17 Найти цитируемый пост)
Ясно. Спасибо. 

http://forum.vingrad.ru/forum/topic-325459/hl/bind/index.html
3й пост с конца  smile 

Автор: borisbn 26.1.2012, 10:44
Цитата(mes @  25.1.2012,  19:24 Найти цитируемый пост)
http://forum.vingrad.ru/forum/topic-325459...bind/index.html
3й пост с конца

тему помню smile (ещё бы, сам спрашивал), но тогда, почему-то, не возникло вопроса про operator == 

Автор: Artemon 27.1.2012, 10:04
borisbn,  Интересный код, есть несколько вопросов:

что означает строка: 

typedef EqualBy< A, QString, &A::x > EqualByX;

И также не совсем ясно, какой адрес возвратится здесь &A::x, ведь объекта еще нет 

Автор: borisbn 27.1.2012, 10:14
Цитата(Artemon @  27.1.2012,  10:04 Найти цитируемый пост)
что означает строка: 

typedef EqualBy< A, QString, &A::x > EqualByX;

а откуда взялся QString ???
код значит следующее:
Имеется шаблонная структура с тремя параметрами шаблона: 1) тип структуры, с которой она работает, 2) тип поля в этой структуре, 3) адрес этого поля внутри структуры (можно сказать смещение, относительно начала).
Далее, даётся определение (typedef) для конкретной реализации этой шаблонной структуры, и этой конкретной реализации даётся новое имя - EqualByX. Этот EqualByX - это та же структура EqualBy, но не для всех случаев жизни, а для 1) A 2) int 3) &A::x

Цитата(Artemon @  27.1.2012,  10:04 Найти цитируемый пост)
И также не совсем ясно, какой адрес возвратится здесь &A::x, ведь объекта еще нет 

возвратится не адрес, а, грубо говоря, смещение внутри A. Затем в структуре EqualBy вычислится конкретный адрес

Цитата(borisbn @  25.1.2012,  16:20 Найти цитируемый пост)
r.*FieldPtr;

или
Цитата(borisbn @  25.1.2012,  16:20 Найти цитируемый пост)
p->*FieldPtr;


Автор: Artemon 27.1.2012, 10:30
Цитата(borisbn @  27.1.2012,  10:14 Найти цитируемый пост)
а откуда взялся QString ???

Это я попробовал как од будет работать с типом QString.

За разъяснения спасибо, все понял.

Автор: borisbn 27.1.2012, 10:32
 smile 
Artemon, привет Челябинску. Недавно там был. Хороший город, но хооооолодно......

Автор: Artemon 27.1.2012, 13:31
Да, холодно, но на Крещение я всеравно искупаляся, настолько было холодно кожа на руках треснула до крови. smile

Автор: Artemon 10.2.2012, 15:07
borisbn,  есть какой-то универсальный вариант чтобы производить поиск в векторе, содержащем объекты классов.

К примеру у меня есть класс:

Код

class MyClass
{
public:
         QString GetA()const;
         QString GetB()const;
         QString GetC()const;
private:
};

QVector<MyClass*> Mas;



Требуется выполнять поиск по вектору, используя разные условия: Obj.GetA() == "1", Obj.GetB() == "2"
Не хотелосьбы использовать для разного поиска разные функциональные объекты.
Также не хотелосьбы внутри функционального объекта использовать if/switch.

Есть какие-то варианты ?

Автор: mes 10.2.2012, 15:48
Цитата(Artemon @  10.2.2012,  14:07 Найти цитируемый пост)
Требуется выполнять поиск по вектору, используя разные условия: Obj.GetA() == "1", Obj.GetB() == "2"
Не хотелосьбы использовать для разного поиска разные функциональные объекты.
Также не хотелосьбы внутри функционального объекта использовать if/switch.

вы написали самоисключающие условия.. 
если вариантов сравнения несколько, должно быть либо нескольк предикатов либо один универсальный с иф.. 
если условие простое в качестве предиката может выступать функция, для более сложных (требующих контекста) приходится использовать функтор..  но функторы бывают "разными" 
скорей всего у Вас проблема в желании не писать кучу классов ? тогда смотрите в сторону бинда и лямбд.. 


Автор: Artemon 10.2.2012, 16:15
mes, да вы верно поняли, я не хочу плодить кучу классов, которые используются как функторы.
Присмотрюсь к бинду и лямбдам.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)