Re[2]: Только Boost!
От: jazzer Россия Skype: enerjazzer
Дата: 03.03.10 10:08
Оценка:
Здравствуйте, igna, Вы писали:

У меня вообще-то тоже только буст

I>На две строки длиннее, зато комментарии не нужны, поскольку нет никаких ничего не говорящих индексов 0, 1, 2, 3.


Т.е. вместо 4 простых понятных функций мы имеем 6 делающих не очень понятно что
По крайней мере, я не понял, что каждая делает. Но вполне допускаю, что разобраться можно, если аккуратно нарисовать на листочке граф зависимостей.
Разбираться с enable/disable_if — это как раз то, от чего хотелось уйти, а ты предлагаешь к этому вернуться.

Если ты по-прежнему считаешь, что твое решение проще, добавь пару перегрузок, скажем, для is_floating (или лучше для double через is_same, а то у тебя is_arithmetic никогда ни сматчится) и для is_array. У меня добавятся две очевидные функции.

I>И можно не только последовательность, но и дерево условий использовать. Ну и Бритва Оккама к тому же.

Не очень понял, к чему бритва Оккама конкретно здесь и в программировании вообще.
Любая функция, кроме main, противоречит этому принципу.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Только Boost!
От: igna Россия  
Дата: 03.03.10 21:55
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Т.е. вместо 4 простых понятных функций мы имеем 6 делающих не очень понятно что


Это не просто 6 функций (точнее шаблона функций), а три раза по две (два), у каждой пары свое имя. f выбирает между arithmetic и не-arithmetic, f_arithmetic — между integral и не-integral, а f_integral — между char и не-char.

J>Если ты по-прежнему считаешь, что твое решение проще, добавь пару перегрузок, скажем, для is_floating (или лучше для double через is_same, а то у тебя is_arithmetic никогда ни сматчится) и для is_array. У меня добавятся две очевидные функции.


У тебя добавятся две очевидные функции и два условия, у меня — то же самое, смотри:

#include <iostream>
#include <string>
using namespace std;

#include <boost/mpl/or.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;
using namespace mpl;

template < class T >
typename disable_if< is_same< T, char >, string >::type
f_integral(T x)
{
    return "integral";
}
template < class T >
typename enable_if< is_same< T, char >, const char* >::type
f_integral(T x)
{
    return "char";
}

template < class T >
typename disable_if< or_< is_integral< T >, is_same< T, double > >, string >::type
f_arithmetic(T x)
{
    return "arithmetic";
}
template < class T >
typename enable_if< is_integral< T >, string >::type
f_arithmetic(T x)
{
    return f_integral(x);
}
template < class T >
typename enable_if< is_same< T, double >, string >::type
f_arithmetic(T x)
{
    return "double";
}

template < class T >
typename disable_if< or_<is_arithmetic< T >, is_array< T > >, string >::type
f(T const& x)
{
    return "generic";
}
template < class T >
typename enable_if< is_arithmetic< T >, string >::type
f(T x)
{
    return f_arithmetic(x);
}
template < class T >
typename enable_if< is_array< T >, string >::type
f(T const& x)
{
    return "array";
}

int main()
{
    cout
        << f('a') << '\n'
        << f(1) << '\n'
        << f(1.) << '\n'
        << f(1.f) << '\n'
        << f("") << '\n'
        << f(main) << '\n'
        ;
}


J>У меня вообще-то тоже только буст


Ну тут enable_cond_c либо относится к используемым "библиотечным" классам, и тогда у тебя не только буст; либо является частью решения, тогда оно в два раза больше моего.
Re[4]: Только Boost!
От: zaufi Земля  
Дата: 03.03.10 23:05
Оценка:
Здравствуйте, igna, Вы писали:

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


J>>Т.е. вместо 4 простых понятных функций мы имеем 6 делающих не очень понятно что


I>Это не просто 6 функций (точнее шаблона функций), а три раза по две (два), у каждой пары свое имя. f выбирает между arithmetic и не-arithmetic, f_arithmetic — между integral и не-integral, а f_integral — между char и не-char.


выделенное звучит очень логично
а связь genericовой функции с массивами и арифметическими типами вообще самоочевидна
Re[4]: Только Boost!
От: jazzer Россия Skype: enerjazzer
Дата: 03.03.10 23:56
Оценка:
Здравствуйте, igna, Вы писали:

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


J>>Т.е. вместо 4 простых понятных функций мы имеем 6 делающих не очень понятно что


I>Это не просто 6 функций (точнее шаблона функций), а три раза по две (два), у каждой пары свое имя. f выбирает между arithmetic и не-arithmetic, f_arithmetic — между integral и не-integral, а f_integral — между char и не-char.

хм... Ладно, вернемся к этому чуть ниже.

J>>Если ты по-прежнему считаешь, что твое решение проще, добавь пару перегрузок, скажем, для is_floating (или лучше для double через is_same, а то у тебя is_arithmetic никогда ни сматчится) и для is_array. У меня добавятся две очевидные функции.


I>У тебя добавятся две очевидные функции и два условия, у меня — то же самое, смотри:


То же самое? Очевидные условия? Ну давай посмотрим на твои условия повнимательнее:
I>
I>template < class T >
I>typename disable_if< or_< is_integral< T >, is_same< T, double > >, string >::type
I>f_arithmetic(T x)
I>{
I>    return "arithmetic";
I>}
I>template < class T >
I>typename disable_if< or_<is_arithmetic< T >, is_array< T > >, string >::type
I>f(T const& x)
I>{
I>    return "generic";
I>}
I>

Что ты там говорил, "f_arithmetic — между integral и не-integral" — не говоря уже об очевидном несовпадении имени и смысла, на которое указал zaufi, что тут делает is_same< T, double >?
И заодно скажи мне, в сколько функций тебе пришлось внести изменения по сравнению с твоим исходным вариантом с 4 условиями (мне самому лень считать).

Не говоря уже о засорении пространства имен — у меня одна единственная фукнция f, а у тебя целый зоопарк: f, f_arithmetic, f_integral...
Причем три f, три f_arithmetic и почему-то всего две f_integral

Боюсь, что ты погорячился насчет простейших, очевидных и прочих эпитетов.

J>>У меня вообще-то тоже только буст

I>Ну тут enable_cond_c либо относится к используемым "библиотечным" классам, и тогда у тебя не только буст; либо является частью решения, тогда оно в два раза больше моего.
в 2 раза? это ты как посчитал?

ЗЫ ты не пишешь библиотечных функций/классов? Или пишешь, но тебе стыдно?
Или это религия новая такая — использовать только то, что дано свыше, и не писать самим всяких там отсутствующих в STL copy_if, а вместо этого либо использовать имеющийся remove_copy_if, либо ждать C++0x?
А если я enable_cond предложу в Boost.Utility и его включат, что ты будешь делать?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Только Boost!
От: zaufi Земля  
Дата: 04.03.10 00:10
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Боюсь, что ты погорячился насчет простейших, очевидных и прочих эпитетов.

складывается ощущение что автор сам слегка запутался в накопипастеных функциях демонстрируя простоту своего решения
Re[2]: template pattern matching - в защиту отдельных услови
От: jazzer Россия Skype: enerjazzer
Дата: 04.03.10 05:29
Оценка:
Здравствуйте, Кодт, Вы писали:

К>А интересно, можно ли вообще раздавать статические приоритеты сигнатурам, не вытаскивая таблицу принятия решений в отдельное место?


На самом деле, таблица принятия решений в одном месте — довольно удобная штука.
Например, в моем проекте без нее не обойтись было никак, и решение с номерами строк и упоминанием условий непосредственно перед функциями не сработало бы по трем причинам:

1) У меня два набора связанных функций (а может быть и больше), которые рулятся одними и теми же (или похожими, см. п.2) условиями. Сам понимаешь, повторять эти условия непосредственно в каждом наборе функций чревато стандартными проблемами копи-пейста и кошмаром в поддержке.
Когда у тебя есть таблица принятия решений, и у этой таблицы, что немаловажно, есть имя, то ты можешь просто запустить поиск по использованию этого имени и увидеть сразу все функции, которые от этой таблицы зависят.

2) Я могу работать с набором условий алгоритмически именно как с набором, т.е. использовать mpl::transform и прочие приятные вещи, если мне нужно сгенерировать сложные условия по имеющемуся списку простых (в моем случае у меня условия на нескольких аргументах, но условие на одном из аргументов всегда одно и то же, поэтому я его могу за один вызов mpl::transform с mpl::and_ прицепить к условиям по остальным аргументам, которые сами по себе выглядят достаточно просто, что сильно повышает читабельность), причем я могу это делать на лету непосредственно при определении конкретной функции.

Выглядит это примерно так (using namespace boost::mpl):
    // исходные условия без учета специального ограничения на первый аргумент
    template < class T1, class T2 >
    struct Conditions {...};

    // с добавкой на первый аргумент в каждом условии
    template < class T1, class T2 >
    struct ConditionsWithPtr
      : transform< Conditions< T1, T2 >
                 , and_< is_pointer< T1 >, _ >
                 >::type
    {};


3) У меня бывает так, что одно и то же условие используется несколько раз в разных функциях (выбор функции в таком случае осуществляется по другим параметрам) — соответственно автоматика с номерами строк не пройдет: придется условие повторить, но тогда оно придет в противоречие с ним же самим, использованным ранее.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Только Boost!
От: igna Россия  
Дата: 04.03.10 06:37
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Что ты там говорил, "f_arithmetic — между integral и не-integral" — не говоря уже об очевидном несовпадении имени и смысла, на которое указал zaufi, что тут делает is_same< T, double >?


f_arithmetic принимает arithmetic и выбирает подходящую специализацию или общее решение. Сначала это был выбор между integral и остальными aritmetic, то есть не-integral; в новом варианте появился дополнительно double, то есть теперь f_arithmetic принимает arithmetic и выбирает между integral, double и всеми остальными arithmetic.

J>И заодно скажи мне, в сколько функций тебе пришлось внести изменения по сравнению с твоим исходным вариантом с 4 условиями (мне самому лень считать).


В две, как и тебе.

J>Не говоря уже о засорении пространства имен — у меня одна единственная фукнция f, а у тебя целый зоопарк: f, f_arithmetic, f_integral...


А у тебя f и Conditions, последнее — мусор.

J>Причем три f, три f_arithmetic и почему-то всего две f_integral


Ну так в соответствии с иерархией типов в поставленной задаче. f выбирает между array — это раз, arithmetic — это два и общим решением — это три; f_arithmetic — между integral (1), double (2) и общим решением (3); f_integral — между char (1) и общим решением (2):


generic
  array
  arithmetic
    integral
      char
    double


А вот в твоем решении эта иерархия потеряна.

J>А если я enable_cond предложу в Boost.Utility и его включат, что ты будешь делать?


Вот оно где.
Re[3]: template pattern matching - в защиту отдельных услови
От: Кодт Россия  
Дата: 04.03.10 09:01
Оценка:
Здравствуйте, jazzer, Вы писали:

J>На самом деле, таблица принятия решений в одном месте — довольно удобная штука.

Фокус в том, что таблица — в одном месте, а функции — в другом хотя и рядышком.
Перекуём баги на фичи!
Re[4]: template pattern matching - в защиту отдельных услови
От: jazzer Россия Skype: enerjazzer
Дата: 04.03.10 09:15
Оценка:
Здравствуйте, Кодт, Вы писали:

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


J>>На самом деле, таблица принятия решений в одном месте — довольно удобная штука.

К>Фокус в том, что таблица — в одном месте, а функции — в другом хотя и рядышком.
Естественно, в другом, иначе как ты сможешь с ней работать как с единым целым

Но ты так односложно отвечаешь — это значит, что ни один из приведенных доводов тебя не убедил?
Или что ни один из доводов не перевешивает разделения?
Или что ответ по пунктам на подходе?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: template pattern matching - в защиту отдельных услови
От: remark Россия http://www.1024cores.net/
Дата: 04.03.10 11:18
Оценка:
Здравствуйте, jazzer, Вы писали:

J>>>На самом деле, таблица принятия решений в одном месте — довольно удобная штука.

К>>Фокус в том, что таблица — в одном месте, а функции — в другом хотя и рядышком.
J>Естественно, в другом, иначе как ты сможешь с ней работать как с единым целым

J>Но ты так односложно отвечаешь — это значит, что ни один из приведенных доводов тебя не убедил?

J>Или что ни один из доводов не перевешивает разделения?
J>Или что ответ по пунктам на подходе?

А чем не нравится "KISS template pattern matching":
http://www.rsdn.ru/forum/cpp/3722508.1.aspx
Автор: remark
Дата: 02.03.10


Так вроде как всё локально — просто добавляешь нужную специализацию с нужным приоритетом. Или дополнительный диспатчер не нравится?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: template pattern matching - в защиту отдельных услови
От: Кодт Россия  
Дата: 04.03.10 11:23
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Но ты так односложно отвечаешь — это значит, что ни один из приведенных доводов тебя не убедил?

J>Или что ни один из доводов не перевешивает разделения?
J>Или что ответ по пунктам на подходе?

Я не могу говорить, убедил или не убедил: была твоя ситуация, твоё решение, тебя удовлетворило, — при чём здесь моё мнение?
Ты опытным путём показал, что отдельный список условий удобен ("есть как минимум одна овца, чёрная как минимум с одного бока").

Лучше я приведу аналогию
// раз
int step(int x)
{
  if(x <= 0)
    return 0;
  else if(x == 1)
    return 1;
  else if(x % 2)
    return x*3+1;
  else
    return x/2;
}

// два
int step0(int) { return 0; }
int step1(int) { return 1; }
int stepO(int x) { return x*3+1; }
int stepE(int x) { return x/2; }

int step(int x)
{
  if(x <= 0)
    return step0(x);
  else if(x == 1)
    return step1(x);
  if(x % 2)
    return stepO(x);
  else
    return stepE(x);
}

// три
bool test0(int x) { return x<=0; }
bool test1(int x) { return x==1; }
bool testO(int x) { return x%2!=0; }
bool testE(int x) { return true; }

bool (*const tests [4])(int) = { test0, test1, testO, testE };

int  (*const steps [4])(int) = { step0, step1, stepO, stepE };

int ztepO(int x) { return x*5+1; }
int  (*const zteps [4])(int) = { step0, step1, ztepO, stepE };

int test(int x)
{
  for(int i=0; i!=4; ++i)
    if(tests[i](x)) return i;
  assert(false); throw wtf;
}
int step(int x) { return steps[test(x)](x); }
int ztep(int x) { return zteps[test(x)](x); }

Понятно, что "три" перспективнее. Но "раз" проще и нагляднее, если всё ограничивается одним разом.
Перекуём баги на фичи!
Re[6]: template pattern matching - в защиту отдельных услови
От: jazzer Россия Skype: enerjazzer
Дата: 04.03.10 12:58
Оценка:
Здравствуйте, remark, Вы писали:

R>А чем не нравится "KISS template pattern matching":

R>http://www.rsdn.ru/forum/cpp/3722508.1.aspx
Автор: remark
Дата: 02.03.10

Почему же не нравится, очень даже нравится

R>Так вроде как всё локально — просто добавляешь нужную специализацию с нужным приоритетом. Или дополнительный диспатчер не нравится?

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

Там еще было две причины озвучено — 1) реюз условий для нескольких семейств функций и 2) автоматическая генерация условий из других условий или из чего еще угодно (метапрограммированием тут можно заняться в полный рост и очень разнообразно, например, привязать к условиям возвращаемые типы, если это можно сделать алгоритмически, из них же сгенерить соответствующие enable_cond-ы и в самих функциях уже использовать нечто совсем простое без копи-пейста).

Но для простых случаев вроде того, что я привел в качестве мотивации в своей статье, твое решение замечательно подходит, включая решение с номерами строк (главное, чтоб это не случилось ниже 500 строки — сразу получишь по рукам от компилятора, у моего ГЦЦ максимальная глубина рекурсивного инстанцирования — 500, хотя на это есть опция), и таких простых случаев, как учит нас практика, большинство


Но для сложных ситуаций, типа той, что у меня в проекте, придется использовать нечто более обобщенное/низкоуровневое (и поэтому менее удобное из-за разделения условий и самих функций).

R>

jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: template pattern matching - в защиту отдельных услови
От: remark Россия http://www.1024cores.net/
Дата: 04.03.10 13:16
Оценка:
Здравствуйте, jazzer, Вы писали:

R>>А чем не нравится "KISS template pattern matching":

R>>http://www.rsdn.ru/forum/cpp/3722508.1.aspx
Автор: remark
Дата: 02.03.10

J>Почему же не нравится, очень даже нравится

R>>Так вроде как всё локально — просто добавляешь нужную специализацию с нужным приоритетом. Или дополнительный диспатчер не нравится?

J>Нет, с дополнительным диспатчером проблем почти нет (за исключением той проблемы, что он абсолютно неприменим в моем проекте — у меня там кучерявые типы аргументов, которые компилятор выводит сам — с диспатчером все перестанет работать и будет одна сплошная ошибка компиляции из-за неразрешимой неоднозначности).

А это как? Вроде же передача через диспатчер не должна ничего менять в плане типов и их выводимости...


J>Там еще было две причины озвучено — 1) реюз условий для нескольких семейств функций и 2) автоматическая генерация условий из других условий или из чего еще угодно (метапрограммированием тут можно заняться в полный рост и очень разнообразно, например, привязать к условиям возвращаемые типы, если это можно сделать алгоритмически, из них же сгенерить соответствующие enable_cond-ы и в самих функциях уже использовать нечто совсем простое без копи-пейста).


J>Но для простых случаев вроде того, что я привел в качестве мотивации в своей статье, твое решение замечательно подходит, включая решение с номерами строк (главное, чтоб это не случилось ниже 500 строки — сразу получишь по рукам от компилятора, у моего ГЦЦ максимальная глубина рекурсивного инстанцирования — 500, хотя на это есть опция), и таких простых случаев, как учит нас практика, большинство


J>Но для сложных ситуаций, типа той, что у меня в проекте, придется использовать нечто более обобщенное/низкоуровневое (и поэтому менее удобное из-за разделения условий и самих функций).


Понятно

R>>

J>

1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: template pattern matching - в защиту отдельных услови
От: jazzer Россия Skype: enerjazzer
Дата: 04.03.10 13:53
Оценка:
Здравствуйте, remark, Вы писали:

R>>>Так вроде как всё локально — просто добавляешь нужную специализацию с нужным приоритетом. Или дополнительный диспатчер не нравится?

J>>Нет, с дополнительным диспатчером проблем почти нет (за исключением той проблемы, что он абсолютно неприменим в моем проекте — у меня там кучерявые типы аргументов, которые компилятор выводит сам — с диспатчером все перестанет работать и будет одна сплошная ошибка компиляции из-за неразрешимой неоднозначности).

R>А это как? Вроде же передача через диспатчер не должна ничего менять в плане типов и их выводимости...

у меня же несколько аргументов, один свободный совсем, а вот другой в некоторых перегрузках зависит от первого и там все срабатывает.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: template pattern matching - в защиту отдельных услови
От: jazzer Россия Skype: enerjazzer
Дата: 05.03.10 06:58
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Я не могу говорить, убедил или не убедил: была твоя ситуация, твоё решение, тебя удовлетворило, — при чём здесь моё мнение?

К>Ты опытным путём показал, что отдельный список условий удобен ("есть как минимум одна овца, чёрная как минимум с одного бока").
К>Понятно, что "три" перспективнее. Но "раз" проще и нагляднее, если всё ограничивается одним разом.

Ну в общем-то да.
Просто моя цель была показать, что решение без отдельных условий не однозначно хуже, и у него есть своя вполне весомая область применения, и что отказ от отдельных условий небесплатен — мы теряем вполне конкретные рулезы (хотя приобретаем другие в виде простоты записи условий в простых случаях).

Т.е, как обычно в нашей профессии, мы имеем выбор из разных вариантов, и в зависимости от задачи у одного будет преимущество над другим.
Сорри, что я не уловил понимания этого в твоем изначальном ответе "Фокус в том, что таблица — в одном месте, а функции — в другом "

Иными словами, нужно пользоваться моим решением, если нужно:
1) переиспользование списков условий для нескольких наборов функций,
2) автоматическая генерация списков условий,
3) непосредственный доступ к сигнатурам каждой перегрузки,
4) использование одного и того же условия для нескольких перегрузок.

Решение Ремарка c __LINE__ подходит для всех остальных случаев, а решение с явным указанием приоритетов — для остальных случаев плюс пункт 4 выше.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.