LINUX.ORG.RU

[C++] Чего вам нехватает в языке?

 


0

0

Может бессмысленный топик, но хотелось бы знать мнение: каких фич языка не хватает по вашему в c++?

З.Ы. Убедительная просьба фанатам других языков программирования воздержаться от комментариев.

Ответ на: комментарий от www_linux_org_ru

>> Ну в той же джаве есть квалификаторы доступа для объектов в рамках пактов. package-private. Хочется такого же...

можешь привести пример, когда классу надо сделать что-то видимым заранее не определенному числу классов, которые возможно будут добавлены в пакет?

Вообще считается что package-private это деталь реализации конкретного пакета и клиент кода не должен ничего добавлять в этот конкретный пакет. Если клиент джентельменского языка не понимает, то пакет можно запечатать цифровой подписью.

Absurd ★★★
()

Очень хочется следующего:

  • Во-первых, должна быть возможность убивать молнией тех, кто кастует указатели к инту;
  • pure-функции. Функция (или метод) со спецификатором pure не может обращаться к глобальным переменным (и к куче), зато может использоваться для вычисления параметров шаблонов, инициализации констант и вообще везде где возможно вызываться на этапе компиляции. Если функция не обозначена как pure, но может быть таковой, то компилятор должен это детектить и опять же предвычислять её;
  • throws как в java;
  • конструкторы explicit по умолчанию и ключевое слово-антоним для «explicit»;
  • игнорирование возвращаемого значения функции должно считаться ошибкой;
  • локальные типы как параметры шаблонов;
  • оператор переноса, причём хорошо бы как у кнута, т.е. operator<-;
  • стандартизация большого числа атрибутов, включая deprecated и прочее;
  • доступ к аргументам функции как к struct, возможность скопировать все аргументы и передать другой похожей функции. И вообще побольше метапрограммирования.
legolegs ★★★★★
()
Ответ на: комментарий от legolegs

локальные типы как параметры шаблонов;

В С++0x есть, GCC 4.5 поддерживает.

Begemoth ★★★★★
()
Ответ на: комментарий от legolegs

Ах да, и ещё: убрать ещё эту legacy-хрень с привидением указателя к массиву и невозможности передавать массив по значению. Мечтать так мечтать.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>Во-первых, должна быть возможность убивать молнией тех, кто кастует указатели к инту;
Возможность для кого?

конструкторы explicit по умолчанию и ключевое слово-антоним для «explicit»;

Зачем?

игнорирование возвращаемого значения функции должно считаться ошибкой;

А что по-вашему не игнорирование?



Booster ★★
()
Ответ на: комментарий от legolegs

>Ах да, и ещё: убрать ещё эту legacy-хрень с привидением указателя к массиву и невозможности передавать массив по значению.
Зачем Вам это?

Booster ★★
()
Ответ на: комментарий от Booster

>>Во-первых, должна быть возможность убивать молнией тех, кто кастует указатели к инту;

Возможность для кого?

Для всех. Ибо нехрен. Или приведите пример, когда это нужно и не опасно.

конструкторы explicit по умолчанию и ключевое слово-антоним для «explicit»;

Зачем?

В моей практике неявное приведение при помощи конструктора почти всегда было нежелательным, т.е. не-explicit конструкторы буквально единичные случаи. Впрочем, тут предлагалось вообще запретить все неявные привидения типов. Сурово, но не лишено здравого смысла.

игнорирование возвращаемого значения функции должно считаться ошибкой;

А что по-вашему не игнорирование?

«не игнорирование»==«использование». С любовью, твой К.О.

Ах да, и ещё: убрать ещё эту legacy-хрень с привидением указателя к массиву и невозможности передавать массив по значению.

Зачем Вам это?

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

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

>Для всех. Ибо нехрен. Или приведите пример, когда это нужно и не опасно.
int в указатель можно, а наоборот нельзя? Почему? Например в колбеках которые ждут указателя, но по факту передаётся не указатель.

В моей практике неявное приведение при помощи конструктора почти всегда было нежелательным, т.е. не-explicit конструкторы буквально единичные случаи.

По-моему как раз наоборот криминала в этом никакого нет, так как обычно приведение работает корректно. Кто нас рассудит? ^)

«не игнорирование»==«использование». С любовью, твой К.О.

Йес, К.О. Теперь сформулируйте термин «использование».

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

Разве нет такой возможности и без передачи массива по значению?




Booster ★★
()
Ответ на: комментарий от legolegs

невозможность определить функцию, принимающую массив заданного размера мне не нужны.

В C++0x есть std::array:

void foo(const std::array<int, 3>& arr);
Begemoth ★★★★★
()
Ответ на: комментарий от Booster

Например в колбеках которые ждут указателя, но по факту передаётся не указатель.

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

Begemoth ★★★★★
()
Ответ на: комментарий от Booster

> int в указатель можно, а наоборот нельзя?

int в указатель тоже нельзя. Потому как у них разные размеры могут быть.

anonymous
()
Ответ на: комментарий от Booster

По-моему как раз наоборот криминала в этом никакого нет, так как обычно приведение работает корректно. Кто нас рассудит? ^)

Использование одноаргументных конструкторов для неявного преобразования типов в моей практике - редкость, у legolegs - тоже. А пропущеный квалификатор explicit у конструктора - из разряда заботливо разложенных грабель, т.к. компилятор сделает преобразование, которого программист не ожидает.

Begemoth ★★★★★
()
Ответ на: комментарий от Booster

>int в указатель можно

Нельзя. Я не упомянул об этом, потому что это уж явный бред. А авторов ваших колбеков, которые ждут не того, что им реально надо - молнией.

>По-моему как раз наоборот криминала в этом никакого нет, так как обычно приведение работает корректно. Кто нас рассудит? ^)

А как вам такой баг:

struct B;
struct A {
A(B &) {}
};
ostream & operator<< (ostream & os, A)
{
return os << "A" << endl;
}
struct B {};
int main ()
{
B b;
cout << b << endl;
}

Всесто вывода может быть, конечно, любая другая операция.

>Йес, К.О. Теперь сформулируйте термин «использование».

Участие функции в составе выражения. У меня бесконечное терпение, так что сразу признай что ты понял о чём речь и предъяви реальные возражения либо согласись.

>Разве нет такой возможности и без передачи массива по значению?

Тут выше привели, но смысла вводить в библиотеку средство, заменяющее базовую функциональность языка, искусственно вырезанную в незапамятные времена по соображениям эффективности я не вижу.

legolegs ★★★★★
()
Ответ на: комментарий от Begemoth

С explicit пожалуй соглашусь.

int в указатель тоже нельзя. Потому как у них разные размеры могут быть.

Если не использовать указатель по его прямому назначению, то почему нет?

Booster ★★
()
Ответ на: комментарий от legolegs

>Участие функции в составе выражения. У меня бесконечное терпение, так что сразу признай что ты понял о чём речь и предъяви реальные возражения либо согласись.
Если оно мне нафик не сдалось, то всё равно делать фиктивное присваивание? Компилятор может и оптимизирует, но это глупо.

Booster ★★
()
Ответ на: комментарий от Booster

Если не использовать указатель по его прямому назначению, то почему нет?

Потому что поощряет кривую архитектуру ПО.

std::function
тебе заменит
void (*) (void*)

Begemoth ★★★★★
()
Ответ на: комментарий от Booster

>Если не использовать указатель по его прямому назначению, то почему нет?

А зачем тебе тогда указатель?

Если оно мне нафик не сдалось, то всё равно делать фиктивное присваивание?

Опять же из моей практики, игнорирование возвращаемого значения - почти всегда ошибка. За пределами далеко ходить не надо: malloc, send, fclose, std::remove_if. Обратных примеров (т.е. когда возвращаемое значение есть, но не всегда нужно - кот наплакал): printf (но не scanf), time.

legolegs ★★★★★
()
Ответ на: комментарий от Begemoth

По-идее надо убрать Си касты вообще. Но кто ж их уберёт когда С++ сохраняет совместимость с Си?

Опять же из моей практики, игнорирование возвращаемого значения - почти всегда ошибка. За пределами далеко ходить не надо: malloc, send, fclose, std::remove_if. Обратных примеров (т.е. когда возвращаемое значение есть, но не всегда нужно - кот наплакал): printf (но не scanf), time.

Всяко бывает. Опять-таки использование ничего ещё не гарантирует.

Booster ★★
()
Ответ на: комментарий от Booster

По-идее надо убрать Си касты вообще. Но кто ж их уберёт когда С++ сохраняет совместимость с Си?

Я бы совместимость с Си ограничил бы поддержкой использования библиотек на Си.

Всяко бывает. Опять-таки использование ничего ещё не гарантирует.

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

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

> Я бы совместимость с Си ограничил бы поддержкой использования библиотек на Си.

так может вам не С++ нужен, а D, Java и т.п.?

lester ★★★★
()
Ответ на: комментарий от legolegs

>Опять же из моей практики, игнорирование возвращаемого значения - почти всегда ошибка.

Может лучше указать дополнительным атрибутом при написании функции, что возвращаемое значение обязательно должно быть получено. ИМХО требовать обработки возвращаемых значений во всех функциях слишком сурово.

pathfinder ★★★★
() автор топика
Ответ на: комментарий от Begemoth

> Я не уверен, что их наличие позволит реализовать полный вывод типов.

Я бы предпочёл бы, чтобы объявления типов были ли бы по возможности необязательными и для top-level определений служили бы в первую очередь для документации.

такое, видимо, не получится — так как Type inference in System F is undecidable however.

я бы предложил некое ключевое слово придумай_тип_исходя_из_того_выражения_что_я_написал, более радикально было бы обойтись без него, но типы все равно иногда *придется* указывать

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от pathfinder

>Может лучше указать дополнительным атрибутом при написании функции, что возвращаемое значение обязательно должно быть получено

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

legolegs ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>я бы предложил некое ключевое слово придумай_тип_исходя_из_того_выражения_что_я_написал

Эээ. А auto из c++0x - это не оно?

legolegs ★★★★★
()
Ответ на: комментарий от Booster

> Если не использовать указатель по его прямому назначению, то почему нет?

Я в шоке. А по какому же еще назначению использовать указатель? Это адрес в памяти. Адрес далеко не всегда поместится в int32.

Судя по твоим высказываниям, тебе просто нельзя программировать на Си!

anonymous
()
Ответ на: комментарий от Begemoth

>>> 2. Наличия только контролируемой перегрузки функций.

А. подробнее? в описании D есть примеры багов языка (из-за перегрузки функций), решение — overload sets


Классы типов в Haskell.


радикальненько
а ты уверен, что это не выльется в глупую писанину?

кроче, чем
int f(Type1 x) {...}
int f(Type2 x) {...}
написать вряд ли получится

наконец, компилятор может попытаться *вывести* тайпкласс для такого рода перегрузки, не все же ему мы должны на блюдечке подавать

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от legolegs

> Эээ. А auto из c++0x - это не оно?

Оно, только локальное и ограниченное.
Вот менее ограниченный пример:

auto apply(f,x) { return f(x); }

здесь только одно слово, никаких template<class R, class A, R f(A)>

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от legolegs

> Опять же из моей практики, игнорирование возвращаемого значения - почти всегда ошибка. За пределами далеко ходить не надо: malloc, send, fclose, std::remove_if. Обратных примеров (т.е. когда возвращаемое значение есть, но не всегда нужно - кот наплакал): printf (но не scanf), time.

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

а вот std::remove_if — отдельная песня, там да

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>auto apply(f,x) { return f(x); }

Частный случай: параметры функции соответствуют параметрам шаблона. Приятный сахарок, не более. auto может быть возвращаемым значением если использовать новый шиворот-навыворотный синтаксис объявления.

legolegs ★★★★★
()
Ответ на: комментарий от Begemoth

>>> 7. Отсутствия бардака с вызываемыми значениями (функции, функции-члены, функциональные объекты).

а разве это можно сделать, сохранив C calling convention?


А это тут при чём? Речь о том, что должны быть только функции.


А как же функции с состоянием (функциональные объекты)?

Если же ты говоришь о том, чтобы

всегда, где требуется int f(int), можно было подать int f'(int, void*) [или как там у нас будут реализованы замыкания, может int f"(int, Foo, Bar, double)]

то вот я и спрашиваю насчет C calling convention

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от legolegs

> Частный случай: параметры функции соответствуют параметрам шаблона. Приятный сахарок, не более. auto может быть возвращаемым значением если использовать новый шиворот-навыворотный синтаксис объявления.

ну перепиши это на с++0х, сравним

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

радикальненько а ты уверен, что это не выльется в глупую писанину?

кроче, чем int f(Type1 x) {...} int f(Type2 x) {...} написать вряд ли получится

короче не получится. Но тут будут две функции f с разными типами. Само же желание ограничить возможности перегрузки функций исходит от их использования вместе с boost::bind (или std::bind из C++0x), там, в случае использования перегруженной функции, необходимо полностью указывать её тип. Хотя лямбды из С++0х должны смячить эту проблему.

наконец, компилятор может попытаться *вывести* тайпкласс для такого рода перегрузки, не все же ему мы должны на блюдечке подавать

Это тоже возможно. Хотя хотелось бы иметь некоторый контроль над тем, что он там выводит.

Begemoth ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

то вот я и спрашиваю насчет C calling convention

Пардон, не подумал об использовании функций на Си. Тогда нужно вводить способ указания calling convention, который был бы не применим в случаях использования замыканий.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Добавлю, что есть мнение, что для функций из одного ретурна "-> decltype()" можно разрешить не писать.

legolegs ★★★★★
()
Ответ на: комментарий от Booster

Ну так все же, какие еще могут быть применения у указателя, кроме как быть адресом в памяти?

anonymous
()
Ответ на: комментарий от anonymous

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

Booster ★★
()
Ответ на: комментарий от Booster

Я знал, что ты это скажешь. Кстати, подумай о том, что зная указатель можно достучаться до объекта не просто за O(1) а сразу за один такт.

legolegs ★★★★★
()
Ответ на: комментарий от legolegs

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

Кстати, подумай о том, что зная указатель можно достучаться до объекта не просто за O(1) а сразу за один такт.

Не понял.

Booster ★★
()
Ответ на: комментарий от Miguel

> Capability calculus позволяет делать замыкания без GC. И, на самом деле, язык с ручным управлением памятью и капабилитями я бы сильно приветствовал.

еще бы ты ссылок кинул на статьи по Capability calculus

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Begemoth

> Нет, lazy evaluation везде. Как в Haskell

тут, наверно, надо сказать твердое «нет», иначе сразу потребуется чистота, побочные эффекты только через монады, и получится хаскель

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от legolegs

> Я знал, что ты это скажешь. Кстати, подумай о том, что зная указатель можно достучаться до объекта не просто за O(1) а сразу за один такт.

А если мы не можем передавать указатель на объект в хэш-таблице, т.к. он может поменяться (а вот хэш не поменяется)?

С другой стороны, я бы предложил вместо «молнии» иметь фичу «запретить любые reinterpret_cast в моем проекте», и чтобы проверял это компилятор.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от Begemoth

Я не понял при чём здесь лямбды и колбеки. В колбэк передаётся либо указатель, либо не указатель. Если нам нужно иное, то придётся привести. Например у майкросфт LPARAM это uint, как быть?

Booster ★★
()
Ответ на: комментарий от Begemoth

> Нет, lazy evaluation везде. Как в Haskell

хотя может у тебя какое-то более проработанное предложение?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от legolegs

>невозможности передавать массив по значению

это очень неэффективно и понравится быдлокодерам. не нужно

annulen ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>С другой стороны, я бы предложил вместо «молнии» иметь фичу «запретить любые reinterpret_cast в моем проекте», и чтобы проверял это компилятор.

вставить grep в Makefile. K.O.

annulen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.