Здравствуйте, Sergeem, Вы писали:
S>Эта идея была предложена Александреску в comp.lang.c++.moderated. S>Гуру нос воротили, а мне понравилось
Прикольно!
S>Короче идея состоит в том, чтобы дать возможность писать:
S>if (a <in> b) { ...
Единственное, что здесь неудобно — это ограничения по выводу типа.
Экземпляр оператора имеет конкретный тип; поэтому все, что можно варьировать — это сигнатуры его метода operator(). (Они могут быть шаблонными).
Правда, можно повыделываться с шаблонами шаблонов...
template < template<class,class> class Op >
struct MetaOp2
{
template< class A, class B >
bool operator() (A a, B b) { Op<A,B> op; return op(a,b); }
};
template < template<class> class Op >
struct MetaOp1A
{
template< class A>
bool operator() (A a, B b) { Op<A> op; return op(a,b); }
};
template < template<class,class> class Op >
struct MetaOp1B
{
template< class A, class B >
bool operator() (A a, B b) { Op<B> op; return op(a,b); }
};
(стоит ли говорить, что на такие подвиги VC не способен).
А чтобы не делать глобальные переменные — экземпляры операторов и метаоператоров, то нужно писать
if(123 <MetaOp1A<less>()> 456) ...
// в данном случае less - это симметричный (по типам) оператор, поэтому можно использовать как 1A, так и 1B.
// или завести макросы#define LESS <MetaOp1A<less>()>
#define IN <MetaOp2<in_t>()>
Перекуём баги на фичи!
Re[2]: как сделать свой оператор в с++
От:
Аноним
Дата:
18.03.03 12:42
Оценка:
Здравствуйте, Кодт, Вы писали:
К>
К>// или завести макросы
К>#define LESS <MetaOp1A<less>()>
К>#define IN <MetaOp2<in_t>()>
К>
[skip]
К>А чтобы не делать глобальные переменные — экземпляры операторов и метаоператоров, то нужно писать К>
К>if(123 <MetaOp1A<less>()> 456) ...
К>// в данном случае less - это симметричный (по типам) оператор, поэтому можно использовать как 1A, так и 1B.
К>// или завести макросы
К>#define LESS <MetaOp1A<less>()>
К>#define IN <MetaOp2<in_t>()>
К>
Нее, вот макросы я не люблю, тем более такие.
А чем плохи глобальные переменные?
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
Но здесь типы будут прибиты гвоздями насмерть.
(Если у объекта-функтора могут быть несколько сигнатур оператора(), то у конкретной функции — ровно одна, своя родная, сигнатура).
Здравствуйте, Sergeem, Вы писали:
S>Эта идея была предложена Александреску в comp.lang.c++.moderated. S>Гуру нос воротили, а мне понравилось
S>Короче идея состоит в том, чтобы дать возможность писать:
S>if (a <in> b) { ...
А что, если вообще избавиться от хелперов?
Почему бы (помечтаем...) не сделать такое:
class in : public custom_operator<in> // некая обвеска - в недрах
{
public:
template<class L, class R> SomeResult operator()(L l, R r) const { ..... }
};
Всё шаманство должен взять на себя базовый класс custom_operator<Op>.
Тонким местом является вывод типа SomeResult.
В STL с этим столкнулись и пошли по пути наименьшего сопротивления: функтор должен быть моделью (а то и потомком) binary_function, где результирующий тип прибит гвоздями.
struct join : custom_operator<join> // находит объединение двух однотипных контейнеров
{
template<class L, class R>
struct result_traits { typedef L result_type };
// по-честному, нужно было сделать частичную специализацию result_traits<L,L>
// но компилятор всё равно надаёт по пальцам, если R не приводим к L
// когда попытается вызвать оператор()template<class L>
L operator()(const L& l, const L& r) const { L v = l; v.append(r); return v; }
};
Вопрос с архитектурой binary_traits пока что оставлю открытым.
Очевидное решение —
* сделать обобщённую версию с расчётом на наличие Op::result_traits<L,R>
* и две специализации, дискриминирующие потомков binary_function<Res,L,R> и generic_binary_function<Res>
— плохо масштабируется.
S>Эта идея была предложена Александреску в comp.lang.c++.moderated. S>Гуру нос воротили, а мне понравилось
"Не плоди сущностей без необходимости" — принцип бритвы Оккама. Теоретически это интересно, и в каком-то приложении, где подобных операций очень много, может даже пригодиться.
Но просто так, ради выпендрежа я бы использовать не стал — лишние зависимости, лишняя путаница, etc.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Sergeem, Вы писали:
S>>Эта идея была предложена Александреску в comp.lang.c++.moderated. S>>Гуру нос воротили, а мне понравилось
S>>Короче идея состоит в том, чтобы дать возможность писать:
S>>if (a <in> b) { ...
К>А что, если вообще избавиться от хелперов?
Уф... Что-то мудрено вышло!
На самом деле хелперы я вставил только для совместимости с Visual'ом, потому как у него проблемы с частичной специализацией. На самом деле, чтобы сделать новый оператор, не нужно даже наследоваться! Просто расширяем namespace cust_op.
namespace cust_op
{
struct my_operator_t
{
template <class T, class U>
bool operator() (const T &lhs, const U &rhs) const
{
return ....;
}
};
}
extern cust_op::my_operator_t my_operator;
...
if (x <my_operator> y)
{
...
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
Здравствуйте, McSeem2, Вы писали:
S>>Эта идея была предложена Александреску в comp.lang.c++.moderated. S>>Гуру нос воротили, а мне понравилось
MS>"Не плоди сущностей без необходимости" — принцип бритвы Оккама. Теоретически это интересно, и в каком-то приложении, где подобных операций очень много, может даже пригодиться. MS>Но просто так, ради выпендрежа я бы использовать не стал — лишние зависимости, лишняя путаница, etc.
Во-во, зачем люди вообще STL придумали, шаблоны, паттерны всякие опять же...
Вот жили 20 лет без шаблонов, и хорошо!
Непонятно!
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
Здравствуйте, Sergeem, Вы писали:
S>Уф... Что-то мудрено вышло! S>На самом деле хелперы я вставил только для совместимости с Visual'ом, потому как у него проблемы с частичной специализацией. На самом деле, чтобы сделать новый оператор, не нужно даже наследоваться! Просто расширяем namespace cust_op.
Во-первых, ты перекрыл глобальный оператор < для ваще-всех типов (естественно, если есть специализации, то в силу вступят они).
Приключения начнутся там, где этот оператор выступает в своей исходной роли.
Например, ты делаешь std::set<YourClass>. И забыл определить для него оператор сравнения... Наготове — дефолтный оператор, который возвращает — сюрприз! — cust_op::operator_arg_t<YourClass,YourClass>
Что скажет кальтенбруннер, то есть, пардон, компилятор в недрах STL?
Во-вторых, ты ограничиваешься предикатами (функторы возвращающие bool). Хорошо, пока это <in>, <not_in>.
А если я делаю, к примеру, векторную алгебру: <crossproduct> ?
Здравствуйте, Sergeem, Вы писали:
S>Во-во, зачем люди вообще STL придумали, шаблоны, паттерны всякие опять же... S>Вот жили 20 лет без шаблонов, и хорошо! S>Непонятно!
Все должно быть у месту. Не надо бросаться в крайности. Если я считаю STL неуместной в какой-то задаче, я ее и не использую. Уместность подобных операторов весьма сомнительна вообще.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, Sergeem, Вы писали:
S>>Уф... Что-то мудрено вышло! S>>На самом деле хелперы я вставил только для совместимости с Visual'ом, потому как у него проблемы с частичной специализацией. На самом деле, чтобы сделать новый оператор, не нужно даже наследоваться! Просто расширяем namespace cust_op.
К>Во-первых, ты перекрыл глобальный оператор < для ваще-всех типов (естественно, если есть специализации, то в силу вступят они).
Что за наезд??!
К>Приключения начнутся там, где этот оператор выступает в своей исходной роли.
Приключения закончатся, если ты внимательно посмотришь исходники.
Serge.
Hасколько проще была бы жизнь, если бы она была в исходниках.
Здравствуйте, Sergeem, Вы писали:
К>>Во-первых, ты перекрыл глобальный оператор < для ваще-всех типов (естественно, если есть специализации, то в силу вступят они).
S>Что за наезд??!
К>>Приключения начнутся там, где этот оператор выступает в своей исходной роли.
S>Приключения закончатся, если ты внимательно посмотришь исходники.
Аааа. Почему-то показалось, что оператор< вне пространства cust_op.
Здравствуйте, McSeem2, Вы писали:
MS>Здравствуйте, Sergeem, Вы писали:
S>>Во-во, зачем люди вообще STL придумали, шаблоны, паттерны всякие опять же... S>>Вот жили 20 лет без шаблонов, и хорошо! S>>Непонятно!
MS>Все должно быть у месту. Не надо бросаться в крайности. Если я считаю STL неуместной в какой-то задаче, я ее и не использую. Уместность подобных операторов весьма сомнительна вообще.