Re[3]: No more ugly functors
От: MaximE Великобритания  
Дата: 08.11.03 17:01
Оценка:
WolfHound wrote:

W> ЗЫ ИМХО container_traits (ну если еще доработать) самое место в STL. Что скажите?


[boost] review request: container_traits
http://groups.yahoo.com/group/boost/files/container_traits/

и еще ацтой по теме: [boost] any interesting in a foreach looping construct?
Posted via RSDN NNTP Server 1.8 beta
Re[7]: No more ugly functors
От: Юнусов Булат Россия  
Дата: 08.11.03 19:12
Оценка: -2
Здравствуйте, Аноним, Вы писали:

А>Булат, Вы промахнулись в этой строчке:

А>
ЮБ>>        return data_[i_-1] + data_[i_++ -2];
А>



Неа, это же постфиксный инкремент, так что этот код эквивалентен
        int rc = data_[i_-1] + data_[i_-2];
        ++i_;
        return rc;
Re[8]: No more ugly functors
От: GarryIV  
Дата: 08.11.03 21:44
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, Аноним, Вы писали:


А>>Булат, Вы промахнулись в этой строчке:

А>>
ЮБ>>>        return data_[i_-1] + data_[i_++ -2];
А>>



ЮБ>Неа, это же постфиксный инкремент, так что этот код эквивалентен

ЮБ>
ЮБ>        int rc = data_[i_-1] + data_[i_-2];
ЮБ>        ++i_;
ЮБ>        return rc;
ЮБ>


А по моему нет. У тебя неопределенное поведение.
WBR, Igor Evgrafov
Re[3]: No more ugly functors
От: MaximE Великобритания  
Дата: 08.11.03 22:25
Оценка:
Здравствуйте, Шахтер, Вы писали:

[]

Ш>Ну так придумайте инкапсуляцию для операторов как свойство языка. Это было бы, по-моему, куда более продуктивно.


Все уже придумано: boost::lambda.

Слышал, что предлагают добавить лямбда-выражения в core language.
Крокодилы в клетке
От: Шахтер Интернет  
Дата: 08.11.03 23:03
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Здравствуйте, Аноним, Вы писали:


А>>Булат, Вы промахнулись в этой строчке:

А>>
ЮБ>>>        return data_[i_-1] + data_[i_++ -2];
А>>



ЮБ>Неа, это же постфиксный инкремент, так что этот код эквивалентен

ЮБ>
ЮБ>        int rc = data_[i_-1] + data_[i_-2];
ЮБ>        ++i_;
ЮБ>        return rc;
ЮБ>


Очень неудобно вставлять (текст) из стандарта.

[Clause 5]
<skipped>

4 Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual
expressions, and the order in which side effects take place, is unspecified.53) Between the previous
and next sequence point a scalar object shall have its stored value modified at most once by the evaluation
of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.
The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full
expression; otherwise the behavior is undefined. [Example:
i = v[i++]; // the behavior is unspecified
i = 7, i++, i++; // i becomes 9
i = ++i + 1; // the behavior is unspecified
i = i + 1; // the value of i is incremented
—end example]

Короче, обьясняю по-простому. Компилятор, разбирая выражение, строит дерево разбора. В дальнейшем, он должен выбрать некоторый порядок обхода этого дерева (усилить отношение частичного порядка до линейного). Вообще говоря, это можно сделать многими разными способами. Более того, здесь таится опасность комбинаторного взрыва, в том смысле, что число всех вариантов обхода растет экспоненциально. Так вот, если для двух таких вариантов вы получите функционально не эквивалентную последовательность операций вы проиграли. И даже не потому, что стандарт относит это к unspecified behavior, хрен с ним со стандартом. А потому, что результат вычисления такого выражения вы отдали на произвол компилятору. Т.е. вполне возможно, что где-нибудь после нескольких лет успешной работы (или даже после нескольки часов просто переключением опций компилятора) вы радикально измените свою программу и будете ооооочень долго искать, где же собака порылась. Можно было бы, конечно, договорится применять side-effectы в определённом месте, но это может войти в противоречие с аппаратурой, поскольку, например, некоторые процессоры прекрасно умеют делать авто-инкремент в регистрах. С анализом таких подвохов в compile-time тоже проблема, поскольку см. выше.
... << RSDN@Home 1.1 beta 2 >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: No more ugly functors
От: Шахтер Интернет  
Дата: 08.11.03 23:43
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Шахтер, Вы писали:


ME>[]


Ш>>Ну так придумайте инкапсуляцию для операторов как свойство языка. Это было бы, по-моему, куда более продуктивно.


ME>Все уже придумано: boost::lambda.


ME>Слышал, что предлагают добавить лямбда-выражения в core language.


Вот если в core language, то это в coreне меняет дело.
... << RSDN@Home 1.1 beta 2 >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Крокодилы в клетке
От: Юнусов Булат Россия  
Дата: 09.11.03 00:16
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Здравствуйте, Юнусов Булат, Вы писали:


ЮБ>>Здравствуйте, Аноним, Вы писали:


А>>>Булат, Вы промахнулись в этой строчке:

А>>>
ЮБ>>>>        return data_[i_-1] + data_[i_++ -2];
А>>>


Ок, значит я неправ. Акела промахнулся
Re: Крокодилы в клетке
От: Павел Кузнецов  
Дата: 10.11.03 08:01
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш> Between the previous and next sequence point a scalar object shall have

Ш> its stored value modified at most once by the evaluation of an expression.
Ш> Furthermore, the prior value shall be accessed only to determine
Ш> the value to be stored. The requirements of this paragraph shall be met for
Ш> each allowable ordering of the subexpressions of a full expression;
Ш> otherwise the behavior is undefined.
Ш> [Example:
Ш> i = v[i++]; // the behavior is unspecified
Ш> i = 7, i++, i++; // i becomes 9
Ш> i = ++i + 1; // the behavior is unspecified
Ш> i = i + 1; // the value of i is incremented
Ш> —end example]

Ш> стандарт относит это к unspecified behavior


Хуже: undefined.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: Крокодилы в клетке
От: Шахтер Интернет  
Дата: 11.11.03 04:04
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


Ш>> Between the previous and next sequence point a scalar object shall have

Ш>> its stored value modified at most once by the evaluation of an expression.
Ш>> Furthermore, the prior value shall be accessed only to determine
Ш>> the value to be stored. The requirements of this paragraph shall be met for
Ш>> each allowable ordering of the subexpressions of a full expression;
Ш>> otherwise the behavior is undefined.
Ш>> [Example:
Ш>> i = v[i++]; // the behavior is unspecified
Ш>> i = 7, i++, i++; // i becomes 9
Ш>> i = ++i + 1; // the behavior is unspecified
Ш>> i = i + 1; // the value of i is incremented
Ш>> —end example]

Ш>> стандарт относит это к unspecified behavior


ПК>Хуже: undefined.


В таком случае попрошу поподробнее. Почему в коментария написано unspecified (опечатка?). В чем разница между unspecified и undefined.
Только не надо отсылать к стандарту. У старенького дяди Шахтёра мозгА в этом стандарте не всё понимает.

И ещё. Раз у нас тут такие знатоки стандарта. В этом коде насколько оправдан вызов transform. Дело в том, что он читает данные из того же массива, в который пишет. Стандарт вроде не определяет, в каком точно порядке transform работает. Может он откладывает запись, например. Или вообще едет сверху вниз (это конечно маловероятно, но возможно). Или запускает несколько потоков на многопроцессорной системе.

Effects: Assigns through every iterator i in the range [ result, result + ( last1 first1))
a new corresponding value equal to op(*( first1 + (i result))
or
binary_op(*( first1 + (i result),
*( first2 + (i result))).

Requires: op and binary_op shall not have any side effects.

Что эта фраза означает?

ЮБ>struct miner {
ЮБ>    int * data_;
ЮБ>    size_t i_;
ЮБ>    miner(int * data) : data_(data), i_(0) { data_[0] = data_[1] = 1; } 
ЮБ>    int operator()(int) {
ЮБ>        if (i_ < 2)
ЮБ>            return ++i_, 1;
ЮБ>        return data_[i_-1] + data_[i_++ -2];
ЮБ>    }
ЮБ>};

ЮБ>int main(int argc, char* argv[])
ЮБ>{
ЮБ>    int d[10] = {0};
ЮБ>    std::copy(d, std::transform(d, d+10, d, miner(d)), std::ostream_iterator<int>(std::cout, "\n")); // имхо так красивше

ЮБ>    return 0;
ЮБ>}
... << RSDN@Home 1.1 beta 2 >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re: Могу предложить альтернативу
От: lboss Россия  
Дата: 11.11.03 05:17
Оценка:
Здравствуйте, folk:


class VIterator
{
public:
    bool    m_break;
    VIterator()
        : m_break(false)
    {
    }
};

template <class TIterator>
class VIteratorImpl : public VIterator
{
public:
    TIterator    m_p;

    VIteratorImpl(TIterator p)
        : m_p(p)
    {
    }
};

template <class TIterator>
inline VIteratorImpl<TIterator>    vIteratorInit(TIterator pStart)
{
    return VIteratorImpl<TIterator>(pStart);
}

template <class TIterator>
inline bool    vIteratorCanContinue(VIterator & pIter, TIterator pEnd)
{
    return static_cast<VIteratorImpl<TIterator>& >(pIter).m_p != pEnd;
}

template <class TIterator>
inline void    vIteratorStep(VIterator & pIter, TIterator pEnd)
{
    ++static_cast<VIteratorImpl<TIterator>& >(pIter).m_p;
}

template <class TIterator>
inline typename TIterator::reference vIteratorGetValue(VIterator & pIter, TIterator pEnd)
{
    pIter.m_break = true;
    return *static_cast<VIteratorImpl<TIterator> & >(pIter).m_p;
}



#define FOREACH(varDef, collection)\
    for(\
        VIterator & pIterator = vIteratorInit(collection.begin());\
        !pIterator.m_break && vIteratorCanContinue(pIterator, collection.end());\
        vIteratorStep(pIterator, collection.end())\
        )\
        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)


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

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> col;
    col.push_back(10);
    col.push_back(20);
    col.push_back(30);

    FOREACH(int val, col)
    {
        printf("%d\n", val);
    }

    return 0;
}
С уважением Вадим.
Re[2]: Могу предложить альтернативу
От: folk Россия  
Дата: 11.11.03 06:10
Оценка:
Здравствуйте, lboss, Вы писали:

L>Здравствуйте, folk:



L>
L>class VIterator
L>{
L>public:
L>    bool    m_break;
L>    VIterator()
L>        : m_break(false)
L>    {
L>    }
L>};

L>template <class TIterator>
L>class VIteratorImpl : public VIterator
L>{
L>public:
L>    TIterator    m_p;

L>    VIteratorImpl(TIterator p)
L>        : m_p(p)
L>    {
L>    }
L>};

L>template <class TIterator>
L>inline VIteratorImpl<TIterator>    vIteratorInit(TIterator pStart)
L>{
L>    return VIteratorImpl<TIterator>(pStart);
L>}

L>template <class TIterator>
L>inline bool    vIteratorCanContinue(VIterator & pIter, TIterator pEnd)
L>{
L>    return static_cast<VIteratorImpl<TIterator>& >(pIter).m_p != pEnd;
L>}

L>template <class TIterator>
L>inline void    vIteratorStep(VIterator & pIter, TIterator pEnd)
L>{
L>    ++static_cast<VIteratorImpl<TIterator>& >(pIter).m_p;
L>}

L>template <class TIterator>
L>inline typename TIterator::reference vIteratorGetValue(VIterator & pIter, TIterator pEnd)
L>{
L>    pIter.m_break = true;
L>    return *static_cast<VIteratorImpl<TIterator> & >(pIter).m_p;
L>}



L>#define FOREACH(varDef, collection)\
L>    for(\
L>        VIterator & pIterator = vIteratorInit(collection.begin());\
L>        !pIterator.m_break && vIteratorCanContinue(pIterator, collection.end());\
L>        vIteratorStep(pIterator, collection.end())\
L>        )\
L>        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
L>


( Напомню свою сигнатуру: #define FOR_EACH_(Decl, First, Last) )

Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.

Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[3]: Могу предложить альтернативу
От: lboss Россия  
Дата: 11.11.03 06:25
Оценка:
Здравствуйте, folk, Вы писали:


F>Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.


F>Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.


Ну я наоборот считаю end() более простой операцией — так как это же fake'овый объект как правило и его проще построить.


Но в любом случае я придумал новый вариант:


class VIterator
{
public:
    bool    m_break;
    bool    m_end;
    VIterator(bool end)
        : m_break(false), m_end(end)
    {
    }
};

template <class TIterator>
class VIteratorImpl : public VIterator
{
public:
    TIterator    m_p;

    VIteratorImpl(TIterator p, TIterator pEnd)
        : m_p(p), VIterator(p == pEnd)
    {
    }
};

template <class TIterator>
inline VIteratorImpl<TIterator>    vIteratorInit(TIterator pStart, TIterator pEnd)
{
    return VIteratorImpl<TIterator>(pStart, pEnd);
}


template <class TIterator>
inline void    vIteratorStep(VIterator & pIter, TIterator pEnd)
{
    ++static_cast<VIteratorImpl<TIterator>& >(pIter).m_p;
}

template <class TIterator>
inline typename TIterator::reference vIteratorGetValue(VIterator & pIter, TIterator pEnd)
{
    pIter.m_break = true;
    TIterator::reference ret = *static_cast<VIteratorImpl<TIterator> & >(pIter).m_p;
    pIter.m_end = (pEnd == ++static_cast<VIteratorImpl<TIterator> & >(pIter).m_p);
    return ret;
}



#define FOREACH(varDef, collection)\
    for(\
        VIterator & pIterator = vIteratorInit(collection.begin(), collection.end());\
        !pIterator.m_end && !pIterator.m_break;\
        )\
        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
С уважением Вадим.
Re[4]: Могу предложить альтернативу
От: folk Россия  
Дата: 11.11.03 06:45
Оценка:
Здравствуйте, lboss, Вы писали:

L>Здравствуйте, folk, Вы писали:



F>>Я тоже думал над подобным вариантом. Но на всякий случай решил не _использовать_ результат аргумента Last на каждой итерации. Это мне показалось более безопасным. Также я допускал что это облегчит жизнь оптимайзеру.


F>>Опосля пришла мысль что лучше кастить к First, чем к Last, т.к. у тех реализаций контейнеров, что я видел, метод begin() устроен либо проще чем end(), либо они примерно одинаковы.


L>Ну я наоборот считаю end() более простой операцией — так как это же fake'овый объект как правило и его проще построить.



L>Но в любом случае я придумал новый вариант:



L>
L>class VIterator
L>{
L>public:
L>    bool    m_break;
L>    bool    m_end;
L>    VIterator(bool end)
L>        : m_break(false), m_end(end)
L>    {
L>    }
L>};

L>template <class TIterator>
L>class VIteratorImpl : public VIterator
L>{
L>public:
L>    TIterator    m_p;

L>    VIteratorImpl(TIterator p, TIterator pEnd)
L>        : m_p(p), VIterator(p == pEnd)
L>    {
L>    }
L>};

L>template <class TIterator>
L>inline VIteratorImpl<TIterator>    vIteratorInit(TIterator pStart, TIterator pEnd)
L>{
L>    return VIteratorImpl<TIterator>(pStart, pEnd);
L>}


L>template <class TIterator>
L>inline void    vIteratorStep(VIterator & pIter, TIterator pEnd)
L>{
L>    ++static_cast<VIteratorImpl<TIterator>& >(pIter).m_p;
L>}

L>template <class TIterator>
L>inline typename TIterator::reference vIteratorGetValue(VIterator & pIter, TIterator pEnd)
L>{
L>    pIter.m_break = true;
L>    TIterator::reference ret = *static_cast<VIteratorImpl<TIterator> & >(pIter).m_p;
L>    pIter.m_end = (pEnd == ++static_cast<VIteratorImpl<TIterator> & >(pIter).m_p);
L>    return ret;
L>}



L>#define FOREACH(varDef, collection)\
L>    for(\
L>        VIterator & pIterator = vIteratorInit(collection.begin(), collection.end());\
L>        !pIterator.m_end && !pIterator.m_break;\
L>        )\
L>        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
L>


И на это есть ответ
Я рассматривал подобный монолитный вариант, но мне подумалось что я смогу повторно использовать элементарные wrap/unwrap для другой задачи, так что в результате сделал на них и поместил их в namespace util (а не в _foreach как в опубликованном варианте).

А вообще это правильно, чем больше удается вынести из мароса в шаблон, тем лучше. В скопе цикла находятся меньше скрытых макросом переменных.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[4]: Могу предложить альтернативу
От: folk Россия  
Дата: 11.11.03 06:51
Оценка:
Здравствуйте, lboss, Вы писали:

L>#define FOREACH(varDef, collection)\

L> for(\
L> VIterator & pIterator = vIteratorInit(collection.begin(), collection.end());\
L> !pIterator.m_end && !pIterator.m_break;\
L> )\
L> for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
L>[/ccode]

Ты что ж творишь? Временное значение нельзя привязывать к неконстантной ссылке.
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[5]: Могу предложить альтернативу
От: e-Xecutor Россия  
Дата: 11.11.03 07:42
Оценка:
Здравствуйте, folk, Вы писали:

F>Здравствуйте, lboss, Вы писали:

L>>#define FOREACH(varDef, collection)\
L>>    for(\
L>>        VIterator & pIterator = vIteratorInit(collection.begin(), collection.end());\
L>>        !pIterator.m_end && !pIterator.m_break;\
L>>        )\
L>>        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
L>>


F>Ты что ж творишь? Временное значение нельзя привязывать к неконстантной ссылке.

Это почему же?

#include <stdio.h>

class Base{
};

class Derived:public Base{
public:
  Derived(){printf("C\n");}
  Derived(const Derived& d){printf("CC\n");}
  ~Derived(){printf("D\n");}
};

Derived getD()
{
  return Derived();
}

int main(int argc,char* argv[])
{
  Base& b=getD();
  printf("hello!\n");
  return 0;
}


Вывод:
C
Hello
D

Re[3]: Крокодилы в клетке
От: Павел Кузнецов  
Дата: 11.11.03 07:51
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>>> <... цитата из 5/4 ...>


Ш>>> стандарт относит это к unspecified behavior


ПК>> Хуже: undefined.


Ш> В таком случае попрошу поподробнее.

Ш> Почему в коментария написано unspecified (опечатка?).

Да, опечатка, даже defect report имеется:
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#351

Ш> В чем разница между unspecified и undefined. Только не надо отсылать

Ш> к стандарту. У старенького дяди Шахтёра мозгА в этом стандарте не всё
Ш> понимает.

В этом стандарте по-настоящему никто все не понимает
Но в данном случае, вроде, есть надежда разобраться:
http://www.rsdn.ru/forum/Message.aspx?mid=215574
Автор: Павел Кузнецов
Дата: 17.03.03


P.S. по поводу std::transform — в отдельном сообщении, если будет время.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: No more ugly functors
От: dad  
Дата: 11.11.03 07:51
Оценка:
ЮБ>>Чем функторы то так не нравятся, рульно же когда цикл в одном месте а алгоритм в другом — нафига обртно все в кучу упихивать то?

Ш>Доказывать с пеной у рта не буду, но по-моему не рульно. Потому что расщепляет некую целостность на два фрагмента, далеко расположенных по тексту друг от друга.


зато использование таких супер макросов как у тебя чрезвычайно рульно..
Веру-ю-у! В авиацию, в научную революци-ю-у, в механизацию сельского хозяйства, в космос и невесомость! Веру-ю-у! Ибо это объективно-о! (Шукшин)
Re[6]: Могу предложить альтернативу
От: folk Россия  
Дата: 11.11.03 09:36
Оценка:
Здравствуйте, e-Xecutor, Вы писали:

EX>Здравствуйте, folk, Вы писали:


F>>Здравствуйте, lboss, Вы писали:

EX>
L>>>#define FOREACH(varDef, collection)\
L>>>    for(\
L>>>        VIterator & pIterator = vIteratorInit(collection.begin(), collection.end());\
L>>>        !pIterator.m_end && !pIterator.m_break;\
L>>>        )\
L>>>        for(varDef = vIteratorGetValue(pIterator, collection.end()); pIterator.m_break; pIterator.m_break = false)
L>>>


F>>Ты что ж творишь? Временное значение нельзя привязывать к неконстантной ссылке.

EX>Это почему же?

EX>
EX>#include <stdio.h>

EX>class Base{
EX>};

EX>class Derived:public Base{
EX>public:
EX>  Derived(){printf("C\n");}
EX>  Derived(const Derived& d){printf("CC\n");}
EX>  ~Derived(){printf("D\n");}
EX>};

EX>Derived getD()
EX>{
EX>  return Derived();
EX>}

EX>int main(int argc,char* argv[])
EX>{
EX>  Base& b=getD();
EX>  printf("hello!\n");
EX>  return 0;
EX>}
EX>


EX>Вывод:

EX>C
EX>Hello
EX>D

EX>


8.5.3/5

A reference to type ``cv1 T1'' is initialized by an expression of type ``cv2 T2'' as follows:

If the initializer expression
— is an lvalue (but is not a bit-field), and ``cv1 T1'' is reference-compatible with ``cv2 T2,'' or
— has a class type (i.e., T2 is a class type) and can be implicitly converted to an lvalue of type ``cv3 T3,'' where ``cv1 T1'' is reference-compatible with ``cv3 T3'' *

[Footnote: This requires a conversion function (class.conv.fct) returning a reference type. --- end foonote]


Не уверен что правильно понял. Наше rvalue класс-типа может быть неявно преобразовано в lvalue?
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[5]: Могу предложить альтернативу
От: lboss Россия  
Дата: 11.11.03 09:56
Оценка:
Здравствуйте, folk, Вы писали:

F>Ты что ж творишь? Временное значение нельзя привязывать к неконстантной ссылке.


Тут ты не прав боюсь...

Тогда бы конструкции такого вида не работали бы:

  void f(A & val);
  
...
  f(A());
С уважением Вадим.
Re[5]: Могу предложить альтернативу
От: lboss Россия  
Дата: 11.11.03 10:00
Оценка:
Здравствуйте, folk, Вы писали:

F>И на это есть ответ

F>Я рассматривал подобный монолитный вариант, но мне подумалось что я смогу повторно использовать элементарные wrap/unwrap для другой задачи, так что в результате сделал на них и поместил их в namespace util (а не в _foreach как в опубликованном варианте).

Не понял аргументации — ибо для практически любой другой задачи проще итераторами пользоваться всё-таки... по моему...

F>А вообще это правильно, чем больше удается вынести из мароса в шаблон, тем лучше. В скопе цикла находятся меньше скрытых макросом переменных.


Вообще-то, по моему, главный принцип (или заслуга) данного подхода — это работающий break, и ясность реализации...
С уважением Вадим.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.