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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Новый C++ - что вы от него хотите, пожелания и замечания для C++0x 
:(
    Опции темы
Любитель
Дата 3.11.2006, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Идея этой темы основана на теме про буст, которая плавно переползла в необходимость (или нет) стандартного ГУИ и другие подобные вопросы. Хотя впрочем мне хотелось начать подобное обсуждение давно. Признаюсь, что я находил старую тему с подобным делом (я в ней участия не принимал), но главный её недостаток в том, что она старая. Много изменилось с того времени (на мой взгляд), да и людей новых (по сравнению с тем временем) много. Потому...

Вообщем, хотелось бы обсудить, что бы вы хотели увидеть в новом C++ (C++0x). Пожалуй не будем разделять (совсем отдельно) языковые фичи и библиотеки, зачастую они переплетаются, да и картина так будет более полная. Вовсе не обязательно, чтобы то, что вы хотите одобрялось (сегодня) комитетом по стандартизации - интересно именно узнать мнения. Можно также писать "возможность X крайне не желательна". Желательно только аргументировать, хотя впрочем я понимаю, что часто думаешь, мне нужно бла-бла-бла, а зачем - фиг его знает. Но нужно! Чем больше будет мнений (надеюсь, что их будет достаточное количество) - тем интересней.

Даже, если вы считаете, что ничего менять не надо - напишите, что C++ уже идеален, дальнейшее его развитие невозможно (или ненужно). Я же всё-таки считаю, что C++ - замечательнейший, но по современным требованиям недоработанный язык. Я считаю важным обеспечить возможность нормального создания библиотек на C++. Сейчас разрабатываются либы или под конкретный компилер (причём извратно), либо на уровне исходного кода. Шаблоны - одно из важнейших средств C++, тем не менее даже export поддерживают единицы компилеров (вроде Comeau), да и то требуют исходников. Конечно, шаблоны (естественно, речь про unmanaged) невозможно по определению скомпилировать, ибо это не готовый код (готовый код - специализации). Но некий промежуточный код можно стандартизировать. При компиляции проекта компилер будет докомпиливать этот код. Достаточно интересен вопрос темплейтов в динамик-либах, но здесь для меня пока всё туманно. Простого (более-менее) решения я не вижу, лишь внедрения вторичного компилятора в рантайм C++ (только для темплейтов), впрочем мне это что-то напоминает ;) . Кстати о динамик-либах, средств для работы с ними мы тоже не имеем. Причём мы должны иметь как синтаксис для компиляции либ, так и классы для их динамической загрузки, просмотра экспортируемых вещей и пр. В связи с этим (хотя не только с этим) возникает необходимость в более мощном RTTI, вплоть до получения адреса функции по её строковому имени. Необходимо также более чётко стандартизировать модель размещения объекта в памяти. Очень желательно так, чтобы мы могли гарантировано знать, что два компилера будут одинаково хранить объекты нашего (произвольной сложности) класса. Я всеми руками и ногами за уменьшение в стандарте implementation defined. Более того, я также требую стандартизации размеров встроенных типов данных. В конце концов в других языках это лишь облегчает жизнь. И посмотрите на добрую кучу библиотек - все определяют для себя типы с гарантированным размером. Не проще и не лучше ли гарантировать это на уровне языка. Исключение, возможно, стоит сделать для специфических вариаций на тему C++ (вроде Embedded C++), хотя по этой теме я вряд ли что скажу.

Стандартизация всех этих вещей приводит нас к портируемости между компилерами готового кода. Также необходимо понятие "проекта" (можете называть это сборкой). Это не замена мейкфайлов (или их альтенатив вроде bjam, qmake, MSBuild и пр.), это нужно в первую очередб для библиотек. + это нас избавляет от явной работы с линкером, который для C++ выглядит всё-таки несколько чужим. В Design and Evolution of C++ мы читаем, что одной из целью служения классической линковке была сометсимость C++ с C и Fortran, чтобы можно было использовать их компоновщики. Бюсь это не дюже практично сегодня. Мы указываем в проекте, какие скомпилированные библиотеки мы используем (тоже проекты) и никакой прилинковки лишней не надо. Всё делается достаточно прозрачно. В числе нерешённых вопросов к комитету мне удалось найти вопрос о том, когда писать угловые скобки для заголовков, а когда кавычки. Была предложена иерархия:
1. Стандартная библиотека C++ (заголовки не обязаны быть файлами)
2. Другие стандартные либы, вроде POSIX
3. API оси (вроде WinaPI)
4. Сторонние либы (вроде буста)
5. "Стандартные" библиотеки компании
6. Общие хейдера проекта (для всех девелоперов)
7. Локальные хейдеры

Повторюсь - вопрос не решён (где граница между кавычками и угловыми скобками). Кстати насчёт инклюда. Сегодня за препроцессором остались лишь условная компиляция и инклюды (остальное реализуемо лучше средставми языка). Есть конечно ещё прагмы и прочая гадось, но они по-моему не достойны столь высокого обсуждения. И если условная компиляция - естественная ниша препроцессора, то инклюд - ну уж нет. Необходимо сделать конструкцию языка инклюд с некоторыми защитами. Например, от дабл-инклюда, от действия юзингов в инклюде и пр. В связи с этим надо более точно определиться с понятиме хейдера. Более того, возможна даже компиляция хейдеров. Что это значит? А это значит извлечение в удобную для компилера форму интерфейса заголовка, для дальнейшего более быстрого использования. А теперь вспомните мои рассуждения о темплейтах...

От такой философии вернёмся к будням программирования. Несколько кейвордов и возможностей. Что я за, что против. Возможно позже я напишу более подробно - пока краткий обзор.

Поддерживаю: перегрузка операторов приведения, перегрузка функторов, свитчи для строк, определение типа енумов, alignof, restricted, real или explicit типедефы и енум (без неявного приведения к фактическому типу или целым числам), final/sealed.

Также хотелось бы увидеть типобезопасную версию вараргов. Скажем так:
Код

void f(std::vector<int> ... args)
{
    std::cout << args.size();
    // ...
}

Компилер в состоянии сгенерить (по заголовку) код вызова такой функции, используя соглашения STL-контейнеров. Вдобавок такая функция (в отличие от сишной) может не иметь аргументов. А спомощью чего-то вроде boost::any получаем также произвольный тип аргументов. Аналогично неплохо бы добавить ещё одну версию main с контейнером (любым) из std::string. Безусловно можно написать что-то вроде
Код

std::vector<std::string>> args(argv, argv + argc)

но согласитесь явное существование сигнатуры эстетически приятней. Естественно приведённый только что код должен работать (с двумя больше без пробела). Ещё надо как-то поругать производителей виндовых компилеров: нефиг выдумывать всякие WinMain! main и точка.

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

Это сообщение отредактировал(а) Любитель - 4.11.2006, 12:23


--------------------
PM MAIL ICQ Skype   Вверх
MAKCim
Дата 3.11.2006, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата

Простого (более-менее) решения я не вижу, лишь внедрения вторичного компилятора в рантайм C++ (только для темплейтов)

Шаблоны в С++ - это абстракция времени компиляции. В этом вся фишка. Во время выполнения все типы известны, ничего выводить не надо и программа работает быстро и эффективно. Даже не представляю шаблоны в run-time
Цитата

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

Это да

Я бы добавил type list-ы ы шаблонах, шаблонные typedef-ы


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

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


Опытный
**


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

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



Цитата(Любитель @  3.11.2006,  12:32 Найти цитируемый пост)
Сегодня за препроцессором остались лишь условная компиляция и инклюды (остальное реализуемо лучше средставми языка). 

Категорически не согласен. Макросы всё ещё являются полноправным средством при написании программ на C++. Далеко не все абстракции можно выразить при помощи одних шаблонов, и, как следствие, отказ от макросов в ряде случаев повлечёт за собой либо необходимость многократно повторять один и тот же код с некоторыми изменениями, либо полностью отказаться от использования некоторых идиом. Макросы могут придавать наглядность коду и с этой точки зрения они иногда просто незаменимы. Приведу несколько примеров.

1) Реализация обобщённой «функции» min
Допустим, на входе min мы имеем фактические параметры разных типов. Только лишь шаблонами тут обойтись нелегко – требуется решить нетривиальную задачу по установлению типа результата. С привлечением макросов проблема решается в 5 сек.:

Код
#define MIN(a, b) min_(1 ? a : b, 0 ? a : b)

template <class T>
    const T &min_(const T &a, const T &b)
{
    return a<b ? a : b;
}

template <class T>
    T &min_(T &a, T &b)
{
    return a<b ? a : b;
}

2) Иногда макросы удобны для устранения из виду несущественных деталей кода.
Рассмотрим шаблон:

Код
template <class T1, class T2, bool bFirst>
    struct ChooseType{ typedef T1 Type; };
template <class T1, class T2>
    struct ChooseType<T1, T2, false> { typedef T2 Type; };

#define CHOOSE_TYPE(T1, T2, bFirst) \
    typename ChooseType<T1, T2, bFirst>::Type

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

Код
template <class T>
    class IsIntegral
{
    static char (&Check(...))   [1];
    static char (&Check(int *)) [2];

public:
    const static bool value =
        sizeof Check(CHOOSE_TYPE(T, float, IsArithmetical<T>::value)(0)) - 1;
};

или непосредственное плюхание шаблона?

Код
template <class T>
    class IsIntegral
{
    static char (&Check(...))   [1];
    static char (&Check(int *)) [2];

public:
    const static bool value =
        sizeof Check(typename ChooseType<T, float, IsArithmetical<T>::value>::Type(0)) - 1;
};

По-моему, первое читается несколько полегче.

3) В языке C++ пока что не предусмотрены манипуляции с шаблонами с переменным числом параметров.
Поэтому иногда (например, при создании обобщённых функторов) требуется создавать серию вариантов шаблонов с разным количеством параметров. Когда-то я поставил перед собой задачу – сделать так, чтобы к итераторам можно было применять operator –>*. Вот примерная реализация:

Код
template <class F>
    struct Functor;

template <class T, class R>
    struct Functor<R (T::*)()>
{
    Functor(T &t, R (T::*f)()) : t(t), f(f) {}
    R operator ()() { return (t.*f)(); }
private:
    T &t;
    R (T::*f)();
};

template <class T, class R, class T1, class T2, ...>
    struct Functor<R (T::*)(T1, T2, ...)>
{
    Functor(T &t, R (T::*f)(T1, T2, ...)) : t(t), f(f) {}
    R operator ()(T1 t1, T2 t2, ...) { return (t.*f)(t1, t2, ...); }
private:
    T &t;
    R (T::*f)(T1, T2, ...);
};

template <class Iter, class F>
    Functor<F> operator ->*(const Iter &it, F f)
{
    return Functor<F>(*it, f);
}

Здесь придётся сделать несколько специализаций класса для разного кол-ва параметров. Это нудная и чреватая ошибками работа, которую как раз-таки лучше перепоручить препроцессору. Для этого достаточно лишь один раз определить серии макросов, где каждый последующий макрос определяется через предыдущий:

Код
#define CODE_VARIANTS_1D_0(Code, Divider)
#define CODE_VARIANTS_1D_1(Code, Divider)    Code(1)
#define CODE_VARIANTS_1D_2(Code, Divider)    CODE_VARIANTS_1D_1(Code, Divider) Divider Code(2)
#define CODE_VARIANTS_1D_3(Code, Divider)    CODE_VARIANTS_1D_2(Code, Divider) Divider Code(3)
...

#define CODE_VARIANTS_2D_0(Code, Divider)
#define CODE_VARIANTS_2D_1(Code, Divider)    Code(1)
#define CODE_VARIANTS_2D_2(Code, Divider)    CODE_VARIANTS_2D_1(Code, Divider) Divider Code(2)
#define CODE_VARIANTS_2D_3(Code, Divider)    CODE_VARIANTS_2D_2(Code, Divider) Divider Code(3)
...

#define CODE_VARIANTS_1_0(Code)
#define CODE_VARIANTS_1_1(Code)        Code(1)
#define CODE_VARIANTS_1_2(Code)        CODE_VARIANTS_1_1(Code), Code(2)
#define CODE_VARIANTS_1_3(Code)        CODE_VARIANTS_1_2(Code), Code(3) ...
...

#define CODE_VARIANTS_2_0(Code)
#define CODE_VARIANTS_2_1(Code)        Code(1)
#define CODE_VARIANTS_2_2(Code)        CODE_VARIANTS_2_1(Code), Code(2)
#define CODE_VARIANTS_2_3(Code)        CODE_VARIANTS_2_2(Code), Code(3)
...

#define CODE_VARIANTS_1D(Code, Divider)    CODE_VARIANTS_1D_64(Code, Divider)
#define CODE_VARIANTS_2D(Code, Divider)    CODE_VARIANTS_2D_64(Code, Divider)

#define CODE_VARIANTS_1(Code)              CODE_VARIANTS_1_64(Code)
#define CODE_VARIANTS_2(Code)              CODE_VARIANTS_2_64(Code)

#define FUNC_VARIANTS(Code)                CODE_VARIANTS_2D(Code,)

#define TEMPLATE_PARAM(n)                  class T##n
#define TEMPLATE_ARG(n)                    T##n
#define FUNC_TEMPLATE_PARAM_CR(n)          const T##n &t##n
#define FUNC_TEMPLATE_PARAM_R(n)           T##n &t##n
#define FUNC_TEMPLATE_PARAM(n)             T##n t##n
#define FUNC_TEMPLATE_ARG(n)               t##n

#define TEMPLATE_PARAMS(n)                 CODE_VARIANTS_1_(TEMPLATE_PARAM, n)
#define TEMPLATE_ARGS(n)                   CODE_VARIANTS_1_(TEMPLATE_ARG, n)
#define FUNC_TEMPLATE_PARAMS_CR(n)         CODE_VARIANTS_1_(FUNC_TEMPLATE_PARAM_CR, n)
#define FUNC_TEMPLATE_PARAMS_R(n)          CODE_VARIANTS_1_(FUNC_TEMPLATE_PARAM_R, n)
#define FUNC_TEMPLATE_PARAMS(n)            CODE_VARIANTS_1_(FUNC_TEMPLATE_PARAM, n)
#define FUNC_TEMPLATE_ARGS(n)              CODE_VARIANTS_1_(FUNC_TEMPLATE_ARG, n)
#define FUNC_TEMPLATE_ARGS_D(Divider, n)   CODE_VARIANTS_1D_(FUNC_TEMPLATE_ARG, Divider, n)

(вроде бы в boost нечто похожее есть, но по некоторым причинам я им не пользуюсь, а потому не могу продемонстрировать здесь пример с использованием boost, ибо не изучал и не знаю его).
Теперь вышеприведённый пример с многоточием можно записать следующим образом:

Код
#define DEF_FUNCTOR(n)                                          \
template <class T, class R, TEMPLATE_PARAMS(n)>                 \
    struct Functor<R (T::*)(TEMPLATE_ARGS(n))>                  \
{                                                               \
    Functor(T &t, R (T::*f)(TEMPLATE_ARGS(n))) : t(t), f(f) {}  \
    R operator ()(FUNC_TEMPLATE_PARAMS(n))                      \
        { return (t.*f)(FUNC_TEMPLATE_ARGS(n)); }               \
private:                                                        \
    T &t;                                                       \
    R (T::*f)(TEMPLATE_ARGS(n));                                \
};

CODE_VARIANTS_2D(DEF_FUNCTOR,)
#undef DEF_FUNCTOR

Можно создавать и другие конструкции. Вот, например, реализация функции WriteLn:

Код
#define DEF_FUNC_WRITELN(n)                     \
template <TEMPLATE_PARAMS(n)>                   \
    void WriteLn(FUNC_TEMPLATE_PARAMS_CR(n))    \
{                                               \
    cout<<FUNC_TEMPLATE_ARGS_D(<<, n)<<endl;    \
}
FUNC_VARIANTS(DEF_FUNC_WRITELN)

Добиться такой простоты без применения макросов невозможно – по крайней мере, на данный момент. Впрочем, выводы делайте сами.

Это сообщение отредактировал(а) UnrealMan - 4.11.2006, 09:38
PM MAIL   Вверх
sergejzr
Дата 3.11.2006, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

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



Цитата(Любитель @  3.11.2006,  11:32 Найти цитируемый пост)
Сегодня за препроцессором остались лишь условная компиляция и инклюды (остальное реализуемо лучше средставми языка)

Хмм.. Как вы реализуете с помощью языка:
Код


#define dprintf printf("%s(%i) ",__FILE__,__LINE__),printf


Одно из самых лучших решений для вывода информации, которое я встречал. (dprintf("Hello"); выведет не только строку, но и позицию в исходнике, где она прописана).
 По сабжу хотелось бы ассоциативных массивов в стандартной либе. И switch/case на строки.

Код

switch(word)
{
case "HELLO":
{
//----
}break;

case "GOODBY":
{
//-----
}break;
default:
}



--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Sartorius
Дата 3.11.2006, 20:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата

Хмм.. Как вы реализуете с помощью языка:

 #define dprintf printf("%s(%i) ",__FILE__,__LINE__),printf



 Можно функцию с переменным числом параметров... потом внутри передавать все это printf и еще макросы печатать  smile  запарно тока... 
PM MAIL ICQ   Вверх
sergejzr
Дата 3.11.2006, 20:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

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



Sartorius, не получится.


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
likehood
Дата 3.11.2006, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


666
**


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

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



Цитата(sergejzr @  3.11.2006,  20:44 Найти цитируемый пост)
По сабжу хотелось бы ассоциативных массивов в стандартной либе.

а чем std::map не устраивает?
PM MAIL   Вверх
bsa
Дата 3.11.2006, 23:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Мне бы очень хотелось получить аналог __property из BCB. Очень удобная штука. Да и реализация ее не так сложна.
Фиксированные типы тоже, имхо, очень нужны (не в ущерб стандартным). Путь даже доступ к ним можно получить подключив определенный заголовочный файл (необходимости жестко встраивать я не вижу). И хотелось бы чтобы они выглядели с явным указанием знаковости и разрядности (__uint32, __sint64 и т.п.).
Стандарт на либы (в т.ч. и динамические) и ГУИ тоже нужен.
Смысла выносить шаблоны в динамические либы не вижу, а вот стандарт на прекомпиляцию (или на использование его результатов) заголовочных файлов не помешал бы.
Всеми руками за строки в switch/case.
Текущая реализация RTTI мне не нравится (может не умею пользовтаься?). Не знаю как у других компиляторов, а у GCC имя объекта (как и виртуальные методы) определяется сразу перед вызовом его конструктора, т.е. если у меня Class2 потомок Class1, а в конструкторе Class1 есть сохранение имени класса, то сохранится Class1, хотя в итоге инициализируется Class2 - это очень напрягает. Было бы неплохо, чтобы сразу задавалось имя объекта, а не менялось перед каждым вызовом конструктора. Да и имя класса выдается какое-то кривое. Почему нельзя использовать для этого стандартные Namespace1 :: Namespace2 :: NamespaceN :: ... :: ClassName1 :: ClassName2 :: ... :: ClassNameN? Потом ведь проще отлаживать будет. Надеюсь, не только я RTTI использую исключительно для отладки?
PM   Вверх
Любитель
Дата 4.11.2006, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Цитата(UnrealMan @  3.11.2006,  19:25 Найти цитируемый пост)
Реализация обобщённой «функции» min

Абсолютно не понял. Почему нельзя убрать первую строку и переименовать min_ в min? Компилер в состоянии выбрать конст- или нет версию.

Цитата(UnrealMan @  3.11.2006,  19:25 Найти цитируемый пост)
2) Иногда макросы удобны для устранения из виду несущественных деталей кода.

Абсолютно не согласен с этим примером. Во-первых, даже в данном случае второое читается проще в силу его понятности. Во-вторых, это извращенское решение (по-моему). В данном случае лучше добавить шаблон, решающий, какой тип тебе нужен. С boost::enable_if и boost::Type_traits (замечу - решения, основанные только на шаблонах) подобные задачи решаются легко и (что немаловажно) естественно.

Цитата(UnrealMan @  3.11.2006,  19:25 Найти цитируемый пост)
3) В языке C++ пока что не предусмотрены манипуляции с шаблонами с переменным числом параметров.

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

Тем не менее, я не говорю выкинуть макросы лёгким движением руки. Я говорю предложить как можно больше типобезопасных, легкочитаемых альтернатив на уровне языка.

Цитата(sergejzr @  3.11.2006,  19:44 Найти цитируемый пост)
По сабжу хотелось бы ассоциативных массивов в стандартной либе.

std::map()?
Упс,  заметил, что про это уже сказали - неважно, повторюсь.

Цитата(sergejzr @  3.11.2006,  19:44 Найти цитируемый пост)
:
#define dprintf printf("%s(%i) ",__FILE__,__LINE__),printf

Ну, конкретно это решение для плюсов вряд ли будет лучшим. Это всё-таки больше чистыми сями попахивает. Во-вторых, те вещи, которые требуют информации о строке, файле, текущей функции - пожалуй, тоже надо отнести к обязанностям препроцессора (по крайней мере я лучшего пока не вижу). Хотя всё таки это не очень хорошо. Тяжело засануть макрос, скажем в неймспейс  smile А ведь в данном случае макрос имитирует обычную функцию...

Цитата(MAKCim @  3.11.2006,  16:37 Найти цитируемый пост)
Шаблоны в С++ - это абстракция времени компиляции. В этом вся фишка. Во время выполнения все типы известны, ничего выводить не надо и программа работает быстро и эффективно. Даже не представляю шаблоны в run-time

Эффективность, к сожалению, будет потеряна, поэтому предпочтительней шаблонный код в статик-либах, тогда при сборке приложения компилер создаст нэтив-код. В принципе же, получаем для шаблонов некоторый промежуточный код, который при запуске приложения рантайм-либа должны развёртывать в нормальный. Точно пока это не представляю, но думаю, это возможно. Тем более не раз слышад подобные идеи от неглупых людей.

Наконец таки проперти. Не поверишь - категорически против. В худшем случае на уровне библиотеки. ИМХО проперти противоречат существующим концепциям плюсов и лишь путают. В Яве прекрасно без ник обходятся - и правильно делают. Некоторые считают, что проперти понятней. В Delphi, с которым приходится работать в универе, скажем проперти есть. В итоге многие у нас в группе лишь путаются с пропертями, т. к. что это толком не знают, а считают их за нормальные переменные. В итоге пишут что-то такое:
Код

Delete(Edit1.Text, 5, 2);

Работать это конечно не будет. в итоге наши преподы рекомендуют (типа универсальное правило) заводить переменные, и присваиать им значение пропертей. А вконце (если надо!) - обратно. Скажем так:
Код

S := Edit1.Text;
Delete(S, 5, 2);
Edit1.Text := S;

Тяжело сказать, что мы что-то приобретаем...
К тому же в стандартной библиотеки сложился уже другой подход. Вспомним, скажем функции классов потоков width, fill, precession. В концепции пропертёвых языков это явно должны были быть проперти. Я против этого.


--------------------
PM MAIL ICQ Skype   Вверх
nickless
Дата 4.11.2006, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

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



А мне бы хотелось поддержки метаклассов и _нормальной_ поддержки указателей на методы классов (method pointers) как в delphi, это бы упростило создание и использование шаблонов типа factory, observer, итд.


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
Любитель
Дата 4.11.2006, 15:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



Цитата(nickless @  4.11.2006,  14:48 Найти цитируемый пост)
метаклассов

Это я отношу к продвинутому RTTI. Хотя в полной мере - против. Слишком запарная реализация (по-моему). Согласен с получением метакласса, при указании некоторого базового класса (в Delphi, если не ошибаюсь class of основан на том, что TObject базовый для всех).

Цитата(nickless @  4.11.2006,  14:48 Найти цитируемый пост)
_нормальной_ поддержки указателей на методы классов 

А чем существующие ненормальны?



--------------------
PM MAIL ICQ Skype   Вверх
nickless
Дата 4.11.2006, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

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



Цитата(Любитель @ 4.11.2006,  14:00)
Цитата(nickless @  4.11.2006,  14:48 Найти цитируемый пост)
_нормальной_ поддержки указателей на методы классов 

А чем существующие ненормальны?

Тем, что завязаны типом на один класс, т.е. если есть 2 не связанных наследствием класса А и B с методами int A::bla1() и int B::bla2 то нет возможности скажем сохранить указатели на bla1 и bla2 в массиве, типы разные. 
В delphi такие указатели используются для реализации событий (events), для С++ есть MOC (используется например в Qt), но реализация на уровне языка мне кажется удобнее.


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
MAKCim
Дата 4.11.2006, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

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



Цитата

Эффективность, к сожалению, будет потеряна, поэтому предпочтительней шаблонный код в статик-либах, тогда при сборке приложения компилер создаст нэтив-код. В принципе же, получаем для шаблонов некоторый промежуточный код, который при запуске приложения рантайм-либа должны развёртывать в нормальный.

И получим очередной С#  smile 


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
UnrealMan
Дата 4.11.2006, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Любитель @  4.11.2006,  11:53 Найти цитируемый пост)
Абсолютно не понял. Почему нельзя убрать первую строку и переименовать min_ в min? Компилер в состоянии выбрать конст- или нет версию.

Я же русским языком написал:

Цитата(UnrealMan @  3.11.2006,  19:25 Найти цитируемый пост)
Допустим, на входе min мы имеем фактические параметры разных типов........ 

Попробуй-ка отправить своей min, например, 1 и 1.5 в качестве параметров. Сразу же получишь ошибку из-за неоднозначности (какой тип должен выбраться в качестве T: int или double? компилятор не может сам сделать выбор в пользу какого-либо варианта).

Цитата(UnrealMan @  3.11.2006,  19:25 Найти цитируемый пост)
2) Иногда макросы удобны для устранения из виду несущественных деталей кода.

Цитата(Любитель @  4.11.2006,  11:53 Найти цитируемый пост)
Абсолютно не согласен с этим примером. Во-первых, даже в данном случае второе читается проще в силу его понятности.

Ну, значит, у нас разное представление о понятности кода :-)

Цитата(Любитель @  4.11.2006,  11:53 Найти цитируемый пост)
Во-вторых, это извращенское решение (по-моему). В данном случае лучше добавить шаблон, решающий, какой тип тебе нужен. С boost::enable_if и boost::Type_traits (замечу - решения, основанные только на шаблонах) подобные задачи решаются легко и (что немаловажно) естественно.

boost пока не входит в стандарт, а это накладывает ограничение на его применимость. Есть ещё люди, которые boost не используют (и, разумеется, не устанавливают), и некоторым, вроде меня, с ними приходится считаться, а значит, возникает и необходимость разрабатывать свои собственные приёмы (либо остаётся кодить по-старинке).

Цитата(Любитель @  4.11.2006,  11:53 Найти цитируемый пост)
Что могу сказать точно не в плюс макросам - большие макросы (коие я заметил в коде) очень плохо проверять на ошибки.

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

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

Одна из возможных реализаций для решения задачи в отношении конкретного метода swap такова:

Код
template <class T> struct HasSwap
{
    template <class T_, void (T_::*)(T_ &)>
        struct CheckSwap { typedef char (&Type)[2]; };

    template <class T_>
        static typename CheckSwap<T_, &T_::swap>::Type HasSwapFn(T_ *);
    static char HasSwapFn(...);

    static const int value = sizeof HasSwapFn((T *)0) - 1;
};

Сразу же бросается в глаза следующий факт: название функции намертво привязано к нашему классу HasSwap. Мы можем создавать шаблоны, где параметры – классы, но имена функций в качестве параметров шаблона мы передавать не можем. Поэтому в общем в виде поставленная задача не имеет решения... без макросов. Да-да, вместо того чтобы для каждого имени метода создавать вручную собственный класс по одной и той же схеме, можно один раз написать общие макросы

Код
#define DEF_METHOD(Method, Ret, Params, Id)                             \
template <class T>                                                      \
class Uutl_ClassMethod_##Method##_##Id                                  \
{                                                                       \
    template <class T_, Ret (T_::*)Params>                              \
        struct MethodClass { typedef char (&Type)[2]; };                \
                                                                        \
    static char (&Check(...))[1];                                       \
    template <class T_>                                                 \
        static typename MethodClass<T_, &T_::Method>::Type Check(T_ *); \
public:                                                                 \
    static const bool bExists = sizeof Check((T *)0) - 1;               \
};

#define CHECK_CLASS_METHOD(Class, Method, Ret, Params, Id)              \
    Uutl_ClassMethod_##Method##_##Id<Class>::bExists
/* два предпоследних параметра используются только в качестве своеобразного
комментария */

и далее задействовать их. Например, создание и использование класса вроде HasSwap будет выглядеть примерно следующим образом:

Код
class UserClassName
...
DEF_METHOD(swap, void, (T &), Swap_identifier) // создаём
....
CHECK_CLASS_METHOD(UserClassName, swap, void, UserClassName &, Swap_identifier)
// используем
....

Цитата(Любитель @  4.11.2006,  11:53 Найти цитируемый пост)
Тем не менее, я не говорю выкинуть макросы лёгким движением руки. Я говорю предложить как можно больше типобезопасных, легкочитаемых альтернатив на уровне языка.

Трудно понять, что ты хочешь сказать. Ведь это

Цитата(Любитель @  3.11.2006,  12:32 Найти цитируемый пост)
Сегодня за препроцессором остались лишь условная компиляция и инклюды (остальное реализуемо лучше средставми языка). 

не я же сочинил? Может, если бы я использовал boost, то думал бы примерно так же, но разрабатывая собственную библиотеку (частично как альтернативу boost, которую с легкостью можно перекинуть на другой комп вместе с проектом), я убедился в том, что такое суждение весьма далеко от истины. После того как поработаешь с абстракциями высокого уровня, читать в некоторых умных книжках рекомендации вроде «не используйте макросы, а используйте шаблоны вместо макросов» просто смешно – создаётся впечатление, что автору по части обобщённого программирования ничего сложнее

Код
template <class T>
T sqr(const T &t)
{
    return t*t;
}

писать больше не приходилось.
PM MAIL   Вверх
Любитель
Дата 7.11.2006, 17:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



UnrealMan, во-первых, всё-таки, если хочется поспорить на тему "Макросы: быть или не быть" - я не против, но маленькая просьба (если действительно хочется) - пускай это будет отдельная тема. Возможно, было бы интересно. Пока же отвечу на некоторые моменты твоего поста:

Цитата(UnrealMan @  4.11.2006,  17:13 Найти цитируемый пост)
Попробуй-ка отправить своей min, например, 1 и 1.5 в качестве параметров. Сразу же получишь ошибку из-за неоднозначности (какой тип должен выбраться в качестве T: int или double? компилятор не может сам сделать выбор в пользу какого-либо варианта).

А ты в своём примере попробуй - сделает ли он выбор?  smile На каком основании он может сделать выбор, что тебе надо возвратить int или double.

Цитата(UnrealMan @  4.11.2006,  17:13 Найти цитируемый пост)
boost пока не входит в стандарт

type_traits точно войдёт, enable_if - очень вероятно.

Цитата(UnrealMan @  4.11.2006,  17:13 Найти цитируемый пост)
Следовательно, изначально можно создать конкретный прототип функции, класса или ещё чего-то (без макроса), протестировать его в действии, а затем уже переделать данное конкретное воплощение в абстрактную форму.

Проектирование наизнанку?

Цитата(UnrealMan @  4.11.2006,  17:13 Найти цитируемый пост)
Пусть, например, требуется решить задачу: установить, есть ли в заданном классе метод с заданными: именем, типами возращаемого значения и параметров

Оператор typeof, который на 90% войдёт в новый стандарт решает это гораздо элегантней + типосейфити и прочее.

Цитата(UnrealMan @  4.11.2006,  17:13 Найти цитируемый пост)
Трудно понять, что ты хочешь сказать

Речь про компатибилити.

Цитата(MAKCim @  4.11.2006,  16:22 Найти цитируемый пост)
И получим очередной С# 

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

Добавлено @ 18:03 
Цитата(nickless @  4.11.2006,  16:01 Найти цитируемый пост)
Тем, что завязаны типом на один класс, т.е. если есть 2 не связанных наследствием класса А и B с методами int A::bla1() и int B::bla2 то нет возможности скажем сохранить указатели на bla1 и bla2 в массиве, типы разные. 
В delphi такие указатели используются для реализации событий (events), для С++ есть MOC (используется например в Qt), но реализация на уровне языка мне кажется удобнее. 

С точки зрения C++ (и моей тоже) подобное поведение будет нелогично. Если нужно - создай абстрактный базовый класс, не забывай про множественное наследование. Это гораздо практичнее.
Насчёт дельфийских ивентов - с системой сигнал/слотов они и близко не лежали. Вспомни, хотя бы, что слотов можно законектить несколько на один сигнал. В Дельфи (насколько я знаю) такого невозможно по определению (архитектура такая). И ещё - советую посмотреть в сторону Boost.Signal (сигнал/слоты, реализованные с помощью языковых возможностей). Достаточно перспективно.



--------------------
PM MAIL ICQ Skype   Вверх
mr.Anderson
Дата 7.11.2006, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Я скажу что-нить маленькое, но я думаю полезное. Очень бы хотелось, чтобы можно было создавать массивы как в PHP. То есть чтобы индексом было, например, выражение. Типа: 
Код

int b = 3;
int arr[ 25+1-b ];

И еще. Чтобы не было заморочек с типами. В РНР это прекрасно работает. То есть РНР сам определяет тип - строковый, символьный, числовой и т.д. Оч удобно. То есть я могу спокойно написать:
Код

$num = 123;
$str = " поросёнка.";

$ans = $num + $str; //получим переменную строкового типа с содержанием "123 поросенка".

Очень удобно было бы без типов, я думаю.


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
sergejzr
Дата 7.11.2006, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

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



sim7, неее, делать из С++ ПХП не надо. То, что тебе надо std:map, как правильно мне посоветовали smile


--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Djuffin
Дата 8.11.2006, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(sim7 @  7.11.2006,  18:23 Найти цитируемый пост)
int arr[ 25+1-b ];

Код

int *array = new int[25+1-b];



Цитата(sim7 @  7.11.2006,  18:23 Найти цитируемый пост)
Очень удобно было бы без типов, я думаю.

:нервный смех:

Да что ты говоришь? Я думаю с такими предпочтениями тебе стоит изучить Ruby.



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


Гентозавр
****


Профиль
Группа: Участник Клуба
Сообщений: 2976
Регистрация: 29.8.2005
Где: Germany

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



Цитата(Любитель @ 7.11.2006,  16:57)
С точки зрения C++ (и моей тоже) подобное поведение будет нелогично. Если нужно - создай абстрактный базовый класс, не забывай про множественное наследование. Это гораздо практичнее.

Это не всегда возможно/удобно, например нельзя написать отдельно скажем класс капсулирующий работу с каким-нибудь алгоритмом шифрования, добавить к нему прогресс ивент и использовать везде и всюду без общего для всех проектов абстрактного класса.

Цитата(Любитель @ 7.11.2006,  16:57)
Насчёт дельфийских ивентов - с системой сигнал/слотов они и близко не лежали. Вспомни, хотя бы, что слотов можно законектить несколько на один сигнал. В Дельфи (насколько я знаю) такого невозможно по определению (архитектура такая). И ещё - советую посмотреть в сторону Boost.Signal (сигнал/слоты, реализованные с помощью языковых возможностей). Достаточно перспективно.

Не обязательно копировать ивенты дельфи, надо сделать лучше  smile 


--------------------
user posted image

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies
- Linus Torvalds
PM MAIL   Вверх
UnrealMan
Дата 9.11.2006, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Любитель @  7.11.2006,  17:57 Найти цитируемый пост)
На каком основании он может сделать выбор, что тебе надо возвратить int или double.

Если ты настолько хорошо знаешь язык, чтобы поднимать такие темы, то, думаю, как-нибудь сам догадаешься. Что касается макросов, то насчёт них я тут ни с кем спорить не собираюсь.
PM MAIL   Вверх
Любитель
Дата 9.11.2006, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Программист-романтик
****


Профиль
Группа: Комодератор
Сообщений: 3645
Регистрация: 21.5.2005
Где: Воронеж

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



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

ЗЫ Не обижайся, но насчёт макросов я всё-таки темку создам (через несколько дней). Спорить - это не плохо (если спорить, а не ргуаться)  smile 

Цитата(nickless @  8.11.2006,  23:57 Найти цитируемый пост)
Это не всегда возможно/удобно, например нельзя написать отдельно скажем класс капсулирующий работу с каким-нибудь алгоритмом шифрования, добавить к нему прогресс ивент и использовать везде и всюду без общего для всех проектов абстрактного класса.

Не понял? Если можно поясни. Создай интерфейс с нужными тебе методами. Потом наследуйся от этого интерфейса и ещё (возможно) чего-нибудь.



--------------------
PM MAIL ICQ Skype   Вверх
archimed7592
Дата 10.11.2006, 01:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



хотелось бы static конструкторов как в c#.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
UnrealMan
Дата 10.11.2006, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(Любитель @  9.11.2006,  19:40 Найти цитируемый пост)
UnrealMan,  просто я не вижу логичных оснований для выбора. 

Т.е. ты считаешь, что в таком коде

int i = 1;
double d = 1.5;
double xMin = i < d ? i : d;

нет логичных оснований для выбора типа результата условного оператора? Или же ты считаешь, что тип результата применения этого оператора определяется динамически? smile

Цитата(Любитель @  9.11.2006,  19:40 Найти цитируемый пост)
Вероятно, ты хочешь возвращаеть double, если хоть один из параметров double?

А что, это не логичное желание? Может, всё же вспомним, что такие продвижения действительно используются, причём не только применительно к тернарному оператору, но и в случае сложения, умножения и т.д.?

Цитата(Любитель @  9.11.2006,  19:40 Найти цитируемый пост)
В этом случае тебе нужен шаблон с двумя параметрами, а возвращаемый тип определяется с помощью некоторого шаблонного класса (или структуры) с типедефом для выбора типа (и соответственно его специализации). 

Нет, мне-то как раз такой геморрой не нужен smile Я просто напишу MIN(1, 1.5), а макрос раскроет это следующим образом

min_(1 ? 1 : 1.5, 0 ? 1 : 1.5)

Теперь RTFM:

Цитата
Операция условия
          выражение-условия:
               логическое-выражение-ИЛИ
               логическое-выражение-ИЛИ ? выражение : выражение-условия

Условные выражения выполняются слева направо. Первое выражение должно быть арифметического типа или типа указателя. Оно вычисляется, и, если результат его отличен от нуля, то результатом условного выражения будет значение второго выражения, иначе результат - значение третьего выражения. Все побочные эффекты вычисления первого выражения могут возникать до вычисления второго или третьего выражения.
Если второе и третье выражение арифметического типа, и типы их совпадают, то таким же будет и тип результата, если они различаются, то выполняются обычные арифметические преобразования, чтобы привести их к общему типу. Если второе и третье выражение являются указателями или выражением-константой, дающим результат 0, выполняются преобразования указателей, чтобы привести результаты выражений к общему типу. Если второе и третье выражение являются ссылками, выполняется преобразование ссылок, чтобы привести их к общему типу. Если второе и третье выражение имеют тип void, общий тип будет void. Если второе и третье выражение имеют один тип класс T, общим типом будет T. Иначе, выражение считается недопустимым. Тип результата есть общий тип. Вычисляется только второе или третье выражение (но не оба). Результат будет адресом, если второй и третий операнд одного типа и являются адресами.

Итак, в данном случае имеем продвижение int в double. Таким образом, оба фактических параметра функции min_ оказываются одного типа – double. Надеюсь, дальше всё понятно.

Цитата(Любитель @  9.11.2006,  19:40 Найти цитируемый пост)
Тем не менее я бы так делать не стал. Почему? Исходя из правила "умолчания, которые явно не понятны плохи" и "лучше пусть не работает, чем работает не хорошо".

Уж не собираешься ли ты критиковать стандартную реализацию условного оператора? smile

Это сообщение отредактировал(а) UnrealMan - 10.11.2006, 11:16
PM MAIL   Вверх
nerezus
Дата 10.11.2006, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вселенский отказник
****


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

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



Как человек, мало знакомый с сабжем, хочу от него потоки(Threads), гуй(GUI) и поддержку сети(сокеты). Все это на уровне языка.


--------------------
Сообщество художников Artsociety.ru
PM MAIL WWW   Вверх
bsa
Дата 10.11.2006, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(nerezus @ 10.11.2006,  12:04)
Как человек, мало знакомый с сабжем, хочу от него потоки(Threads), гуй(GUI) и поддержку сети(сокеты). Все это на уровне языка.

Лучше не языка, а стандартной библиотеки. Это более логично, имхо.
PM   Вверх
nerezus
Дата 11.11.2006, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вселенский отказник
****


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

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



Ну да )
Но стандартная библиотека - это же часть языка )
Я же не сказал, что на уровне синтаксиса =)


--------------------
Сообщество художников Artsociety.ru
PM MAIL WWW   Вверх
archimed7592
Дата 12.11.2006, 20:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



ещё хотелось бы использовать ф-ции в качестве параметров шаблона. причем как и обыкновенные, так и thiscall.


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
archimed7592
Дата 12.11.2006, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



и чтоб стандарт позволял делать такие вот извращения
Код
template <typename T>
inline bool default_comp (T &el1, T &el2)
{
    return el1 > el2;
}

template <typename T>
inline void default_swap (T &el1, T &el2)
{
    T temp = el1;
    el1 = el2;
    el2 = temp;
}

template <typename T, function bool comp (T el1, T el2) = default_comp<T>, function void swap (T &el1, T &el2) = default_swap<T>>
void qsort (T *start, T *end)
{
    // ...
    if (F (*i, *j))
        swap (*i, *j);
    // ...
}

inline bool comp1 (int el1, int el2)
{
    return el1 < el2;
}
inline void swap1 (int &el1, int &el2)
{
    int temp = el1;
    el1 = el2;
    el2 = temp;
}

inline bool comp2 (BigStruct &el1, BigStruct &el2)
{
    return el1->some_field > el2->some_field;
}
inline void swap (BigStruct &el1, BigStruct &el2)
{
    int temp = el1->some_field;
    el1->some_field = el2->some_field;
    el2->some_field = temp;
}

// ...

qsort (arr, arr + len);
qsort<int, comp1, swap1> (arr, arr + len);
qsort<BigStruct, comp2, swap2> (struct_arr, struct_arr + len);
qsort<BigStruct, BigStruct::operator >, swap2> (struct_arr, struct_arr + len);
qsort<BigStruct, some_object.some_compare_func, swap2> (struct_arr, struct_arr + len);
qsort<BigStruct, some_pointer_to_object->compare_func, swap2> (struct_arr, struct_arr + len);
qsort<BigStruct, (*some_pointer_to_object).compare_func, swap2> (struct_arr, struct_arr + len);
// etc...
заметьте в случае comp2 сигнатура отличается от шаблонной, но с точки зрения синтаксиса вызов этих ф-ций одинаковый...

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


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
UnrealMan
Дата 13.11.2006, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(archimed7592 @  12.11.2006,  20:23 Найти цитируемый пост)
ещё хотелось бы использовать ф-ции в качестве параметров шаблона. причем как и обыкновенные, так и thiscall.

Не понял... А передача указателей на функции и методы в качестве шаблонных параметров чем не устраивает?

Цитата(archimed7592 @  12.11.2006,  20:50 Найти цитируемый пост)
и чтоб стандарт позволял делать такие вот извращения

Ну, тут ещё надо разрешить шаблонные параметры по умолчанию для шаблонов функций – пока что такое дозволено лишь в отношении шаблонов классов. А так можно использовать что-то вроде

Код
template <typename T>
    bool default_comp(const T &el1, const T &el2)
{
    return el1 > el2;
}

template <typename T>
    void default_swap(T &el1, T &el2)
{
    T temp = el1;
    el1 = el2;
    el2 = temp;
}

template <class T, bool (*comp)(const T &el1, const T &el2), void (*swap)(T &el1, T &el2)>
    void qsort(T *start, T *end)
{
    // ...
}

template <class T>
    void qsort(T *start, T *end)
{
    qsort<T, default_comp<T>, default_swap<T> >(start, end);
}

// ...

Цитата(archimed7592 @  12.11.2006,  20:50 Найти цитируемый пост)
думаю разница между вызовом ф-ции по указателю и вызовом конкретной ф-ции всем известна

Дык тут указатель может быть только на конкретную функцию, поэтому её встраиванию ничто не препятствует.

P.S. to archimed7592. Вообще этакие темы надо обсуждать там, где есть такие яркие личности, как Hryak и Flex Ferrum :-)
PM MAIL   Вверх
archimed7592
Дата 13.11.2006, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



Цитата(UnrealMan @  13.11.2006,  21:55 Найти цитируемый пост)
Не понял... А передача указателей на функции и методы в качестве шаблонных параметров чем не устраивает?
да, что-то я проглючил. почему-то считал, что передается указатель в переменной...только сейчас дошло, что параметры шаблонов в любом случае константы smile но всё равно не получиться для stdcall подсунуть thiscall для конкретного объекта и наоборот, а хотелось бы - проблемы в реализации быть не должно...почему не сделали ещё - хз.

Цитата(UnrealMan @  13.11.2006,  21:55 Найти цитируемый пост)
P.S. to archimed7592. Вообще этакие темы надо обсуждать там, где есть такие яркие личности, как Hryak и Flex Ferrum :-)
тему поднимать неохота, а здесь она уже есть...флаг в руки, поднимай тему на сорсах, будем обсуждать с яркими личностями smile 



--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
UnrealMan
Дата 14.11.2006, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(archimed7592 @  13.11.2006,  21:26 Найти цитируемый пост)
но всё равно не получиться для stdcall подсунуть thiscall для конкретного объекта и наоборот, а хотелось бы - проблемы в реализации быть не должно...

А в каком виде ты себе представляешь такие «подсовывания»? Если я правильно понял, ты хочешь связывания (binding) на этапе компиляции. Но для связывания требуется объект, содержимое которого на этапе компиляции не известно. Т.е. получается, что компилятору придётся на ходу генерировать некую вспомогательную функцию, объект посылать как полуявный (заданный внутри <>, а не () ) параметр шаблонной функции и потом связывать его со сгенерированной вспомогательной функцией. Полагаю, для разработчиков компиляторов реализация такого – геморрой ещё тот... А в случае передачи cdecl вместо thiscall я вообще не представляю, что должно происходить (что будет делать cdecl-функция – игнорировать this-параметр? или параметров у неё должно быть на один больше, и один из них будет выступать в роли this?)

Цитата(archimed7592 @  13.11.2006,  21:26 Найти цитируемый пост)
поднимай тему на сорсах, будем обсуждать с яркими личностями 

Что-то идей пока нету, с чего б беседу начать. Вот коли появится какая мысл́я – подниму...


Это сообщение отредактировал(а) UnrealMan - 14.11.2006, 11:58
PM MAIL   Вверх
archimed7592
Дата 14.11.2006, 23:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



Цитата(UnrealMan @  14.11.2006,  12:00 Найти цитируемый пост)
А в каком виде ты себе представляешь такие «подсовывания»?
я представляю себе это так: семантически, ф-ция - это набор аргументов + возвращаемое значение. т. е. семантически разницы между f() и obj.f() и pobj->f() нету. чтобы работало следующее:
Код
temp_func<f> (...);
temp_func<obj.f> (...);
temp_func<(pobj->f)> (...);
т. е. чтобы в шаблоне описывалась только семантика, а реализация подставляется во время компиляции. как в #define...все равно компилятор генерит по экземпляру на каждую специализацию. собственно и все чего я хочу.

Цитата(UnrealMan @  14.11.2006,  12:00 Найти цитируемый пост)
Если я правильно понял, ты хочешь связывания (binding) на этапе компиляции.
угу. во время компиляции. т. е. продвинутого препроцессинга smile

Цитата(UnrealMan @  14.11.2006,  12:00 Найти цитируемый пост)
Но для связывания требуется объект, содержимое которого на этапе компиляции не известно.
что значит неизвестно? когда ты пишешь f () - все известно. когда пишешь obj.f () - тоже. в шаблоне же, на этапе специализации тоже все известно.

Цитата(UnrealMan @  14.11.2006,  12:00 Найти цитируемый пост)
 Т.е. получается, что компилятору придётся на ходу генерировать некую вспомогательную функцию, объект посылать как полуявный (заданный внутри <>, а не () ) параметр шаблонной функции и потом связывать его со сгенерированной вспомогательной функцией
ну вот генерит компилятор конкретную специализацию. он все знает про эту ф-цию. зачем ему нужны какие-то вспомогательные вещи? точнее говоря может и нужны, но только для своего внутреннего представления структуры кода, но в итоговом бинаренике - как будто препроцессор поработал и наделал много copy-paste smile

Цитата(UnrealMan @  14.11.2006,  12:00 Найти цитируемый пост)
полагаю, для разработчиков компиляторов реализация такого – геморрой ещё тот...
ну препроцессор же написали smile





--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
archimed7592
Дата 15.11.2006, 06:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



зы. а кто-нить располагает информацией, когда выйдет новый станадарт? 2007? 2008? 2009? как быстро появятся компиляторы для этого стандарта? в прошлый раз (в 2003 году) как быстро появились?


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
UnrealMan
Дата 15.11.2006, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
я представляю себе это так: семантически, ф-ция - это набор аргументов + возвращаемое значение. т. е. семантически разницы между f() и obj.f() и pobj->f() нету. 

obj (или *pobj) – это один из аргументов функции, и от этого никуда не денешься.

Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
т. е. чтобы в шаблоне описывалась только семантика, а реализация подставляется во время компиляции. как в #define...

Ну ты сравнил :-) Директивы препроцессора и шаблоны – это почти совсем разные вещи. Общее у них только то, что с помощью них можно создавать абстракции (а при их объединении можно получить более мощные абстракции).

Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
все равно компилятор генерит по экземпляру на каждую специализацию. собственно и все чего я хочу

Дело в том, что количество параметров, передаваемых в функцию в данных вариантах

temp_func<f> (...);
temp_func<obj.f> (...);

разное.

Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
что значит неизвестно? когда ты пишешь f () - все известно. когда пишешь obj.f () - тоже. в шаблоне же, на этапе специализации тоже все известно.

Ну, смотри:

Код
struct A
{
    int n;
    void f() { cout<<n<<endl; }
};

template <void (*pf)()>
    void Func() { pf(); }

int main()
{
    A a;
    a.n = 3;
    Func<a.f>(); // что будет тут?
}

Что будет при вызове функции pf в шаблонной функции Func? Очевидно, для корректного отрабатывания такого вызова нужен объект a. Откуда он возьмётся? Как ни крути, его придётся передавать в качестве отдельного параметра Func (подобно тому, как в вызове a.f() он в качестве отдельного параметра (this) передаётся в функцию f). Реализация шаблона сама должна везде подставлять неявный аргумент a при всяком вызове pf. Сигнатура у pf теперь не соотвествует её действительному статусу: да, используется она как void (pf)(), но в сущности это будет прежняя void (A:smilef)(), переданная как шаблонный аргумент. Это в общем-то серьёзный минус. Что, например, будет, если кто-то вдруг захочет присвоить pf некоторому указателю:

Код
void (*pf_)() = 0;
template <void (*pf)()>
    void Func()
{
    pf();
    pf_ = pf; // чего тут надо делать?
}

Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
ну вот генерит компилятор конкретную специализацию. он все знает про эту ф-цию. зачем ему нужны какие-то вспомогательные вещи

Ну, про вспомогательную функцию эт я загнул, конечно...

Цитата(archimed7592 @  14.11.2006,  23:40 Найти цитируемый пост)
ну препроцессор же написали 

В препроцессоре идёт банальная обработка на уровне текста программы, чего не скажешь о шаблонах, поэтому сравнивать их в таком контексте как-то неразумно.
PM MAIL   Вверх
archimed7592
Дата 15.11.2006, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


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

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



Цитата(UnrealMan @  15.11.2006,  11:46 Найти цитируемый пост)
obj (или *pobj) – это один из аргументов функции, и от этого никуда не денешься.
без сомнений. но я же сказал: семантически. ты же конкретно, ручками не передаешь этот аргумент? вот представь, как объясняют это начинающим в школе (или где ещё там)? что мол ф-ция просто исполняется в контексте конкретного объекта. или про ссылки. что это просто "синоним" переменной. так ведь? вот с точки зрения начинающего разницы между вызовом этих двух ф-ций нет:
Код
void func (type arg);
void ref_func (type &arg);
// ...
type var = ...;
func (var);
ref_func (var);
если он конечно не передает константу вместо переменной (но тогда он получает ошибку компиляции - то же самое можно выдать, когда не получается использовать данную ф-ции в этом шаблоне)...
Цитата(UnrealMan @  15.11.2006,  11:46 Найти цитируемый пост)
Что будет при вызове функции pf в шаблонной функции Func? Очевидно, для корректного отрабатывания такого вызова нужен объект a. Откуда он возьмётся? 
ну как откуда. естественно не с потолка smile
значит ещё раз как я себе это представляю: вот есть у наc зашаблоненный qsort. берем и пишем
Код
template<..., F, ...>
qsort (...)
{
    // ...
    F (a, b);
    // ...
}
// ...
qsort<..., func, ...> (...);
qsort<..., ref_func, ...> (...);
qsort<..., obj.func, ...> (...);

что я хочу, чтобы из этого получилось: 3 ф-ции
Код
qsort (...)
{
    // ...
    func (a, b);
    // ...
}

qsort (...)
{
    // ...
    ref_func (a, b);
    // ...
}

qsort (...)
{
    // ...
    obj.func (a, b);
    // ...
}
т. е. обычный копи-пэйст. что же касается контекста thiscall, т. е. того заветного лишнего аргумента - ну как-то он должен передаваться в ф-цию (если она не inline - иначе вопросов вообще никаких не должно быть) средствами компилятора - это уже его проблемы - через стек или через регистры...не суть важно, главное, что проблемы в этом никакой нет.

зы. кстати, насчет передачи this...вот взять какой-нить шаблончик из нэймспейса std и передать ему в качестве аргумента ф-цию из другого нэймспэйса? компилятор же допетривает, что так и так и что это имя из другого нэймспэйса. т. е. как-то он эту ситуацию разруливает. не лучший пример, конечно, но, тем не менее, если задуматься, то семантически разницы между этими вещами большой нету. ну объект, ну нэймспэйс...у нэймспэйса адреса, правда, нету, но это так, мелочи... smile
я отлично понимаю, что звучит все это как-то неубедительно...может даже глупо, но если именно с "глупой" точки зрения на это посмотреть, забыв про тот низкий уровень, где есть разница между stdcall и thiscall, между byval и byref, то идея вполне имеет право на жизнь...


--------------------
If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas.
© George Bernard Shaw
PM Jabber   Вверх
Daevaorn
Дата 15.11.2006, 17:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

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



Цитата(archimed7592 @  15.11.2006,  13:30 Найти цитируемый пост)
то идея вполне имеет право на жизнь

Имеет. Только толку будет не много. В том варианте, что ты предлагаешь буду куча кодогенирации. Ещё проблема - это контроль времени жизни obj.
Для С++ существует много различных релизаций обобщенных обратных вызовов и делигатов. Поэтому насущей необходимости в добавлении чего-то на подобие это в язык, мне кажется, нет.
PM MAIL WWW   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

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

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


 




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


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

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