Pull to refresh

Comments 96

А ведь дата выхода уж намечена, красные ленточки натянуты, водка на фуршетных столах греется, а жаркое — остывает.


Тем не менее уже начали думать над стандартом C++1x.
Вспоминая сколько времени ушло на разработку текущего и поддержку компиляторами этот факт как-то не радует.
А там особо улучшать нечего. C++ — язык одиночек, команды даже шаблоны не тянут. Поэтому у каждого заинтересованного своё мнение, каким он должен быть.
Ещё немного, и C++ действительно станет языком одиночек. Максимум, что этому языку светит лет через 10 — это роль C, и это при том, что для последнего написать компилятор не в пример легче.
А это и есть его целевая ниша. Шаблоны — это порог абстракций, за пределами которого межчеловеческое взаимодействие очень туго работает. К примеру, мне крайне тяжело представить ненадуманную ситуацию, когда один член команды пишет специфический для проекта шаблон, а другие его инстанцианируют. Не говоря уже о шаблонных шаблонных параметрах.
А роль C++ как C (если речь про низкоуровневый и/или очень быстрый код) — она не через 10 лет у C++ будет такая, она уже 10 лет у C++ такая :) по крайней мере 5 лет точно. Там где нужна скорость и отточенность — не место 10 головам, критичные куски везде пишутся одним-двумя профессионалами. Там же, где скорость и отточенность кода не так критичны, не место для binary-oriented аскетичности.
Судя по темпам, лучше бы назвали его C++2x, меньше ошибка была бы.
Не больно-то грустно будет без перечисленных фич. Частенько оказывается, что даже широко известные языковые средства находят довольно неожиданные применения, например.
Офигеть, ничего революционного, что Страуструп хотел в C++0x, так и не вышло. Я имею ввиду gc и reflection. Хотя gc было бы самой главной фичей C++0x. Протараторили 5 лет и вот нате вам. Обидно за С++.
Толсто. В С++0x столько революционного и нового, что разбираться будут ещё лет десять.
Вот именно, вместо выкатывания вещей, которые must have уже практически везде — тот же GC, выкатывают еще 800 страниц всяких синтаксических перделок, без введения действительно революционных (для C++) и нужных изменений. Напомните мне, сколько mainstream языков появилось начиная с 1995 года без поддержки GC? Я не знаю ни одного.
UFO just landed and posted this here
А как этого добились в С++/CLI? Хотя там была цель скрестить все с .Net'ом и не особо парились с реализацией. Почему нельзя было сделать нечто подобное? При чем GC вывалилось только под конец из C++0x, хотя было с самого начала в roadmap'е.
Возможно боялись поломать совместимость — но в жизни C++ уже ломал обратную совместимость с C, и вроде прошел этот этап ломки и боязнь изменений, а вот опять.
Хотя Страуструп, сам создатель и бог С++, был за GC и не был против нарушения обратной совместимости.
Я поддерживаю мнение, что комитет C++0x это какие то деверсанты. Есть и язык D, и новый язык Go — и все более совершенны, хотя не в mainstream'е.
UFO just landed and posted this here
А почему бы им не изменить язык, добавить какого-то специфичного синтаксиса, managed area как в С++/CLI. А в C мне кажется достаточно не сложно было бы организовать GC?

Почему-то мне кажется, что C++ больше связан с Legacy разработкой? Я не спорю новые проекты существует, но появление некоторой специфичной среды улучшит ситуацию для самого языка и позволит перевести те существующие проекты, где он нужен, на те приемы, которые современные, а не переписывать проекты на новые языки.
В ObjC и D низкоуровневые возможности как-то уживаются с GC.
А сколько вообще mainstream языков появилось начиная с 1995?
Ну, почти весь скриптовый веб + вся платформа .NET (а в ней много языков).
В С++0x столько революционного и нового

Сколько? Правда, интересно, что именно из нововведений является революцией, чего не было в других известных языках.
Революционного и нового в для C++, очевидно же (:
Вы действительно ожидаете, что я здесь напишу километровый комментарий на тему всего-подряд-нового в C++0x? Да тут на несколько статей не опишешь. Вкратце предлагаю взять статью из Википедии и разделить новшества на две части: пришедшие из boost-а и возникшие сами по себе. Так вот для последних (за исключением overrides, final, range-based for и может быть чего-нибудь ещё) практически невозможно найти статически типизированные языки, в которых оно реализовано.
Я вас умоляю, разбираться в C++ по десять лет будут не из-за новых фич, а из-за общей сложности и костыльности языка. Просто сравните с D.
новый проект на чистом С++/CLI никто начинать не будет

Ну категорично не стоит говорить, у нас вот в проекте активно создаются компоненты на нем, чтобы обеспечить приемлемое быстродействие (все самое важное делается в unmanaged коде) и возможность вызова и коммуникации с частями программы, написанными на C#.
В самом деле, управляемый С++, странноватое детище Microsoft, созданное даже не как новый язык, а как «мостик» между старым кодом на С++ и платформой .NET, имеет почти все описанное в статье — и концепты, и сборщик мусора, и модули, и всю мощь библиотеки классов .NET и Reflection.

Тут надо объяснить, что Reflection, сборка мусора и остальные плюшки доступны только для managed классов (для тех, кто не знает в C++ CLI есть два типа классов — первый, который компилируется в MSIL и второй — который компилируется в нативный код) и традиционные возможности C++ расширяют слабо. Если вы пишете неуправляемый класс, то получаете не больше, чем в любом другом компиляторе С++.
И да, забыл еще добавить. Если после прочтения моего комментария неясно, почему бы не начать писать все классы управляемыми в C++ CLI, то следует вспомнить, что на управляемые классы распространяются все ограничения CLR, например такие как:
1) Нет множественного наследования классов (что, может и к лучшему)
2) Все ссылочные типы попадают в уборку мусора
3) Управляемый тип не может иметь поле неупрявляемого типа не по указателю
Тут надо объяснить, что Reflection, сборка мусора и остальные плюшки доступны только для managed классов (для тех, кто не знает в C++ CLI есть два типа классов — первый, который компилируется в MSIL и второй — который компилируется в нативный код) и традиционные возможности C++ расширяют слабо. Если вы пишете неуправляемый класс, то получаете не больше, чем в любом другом компиляторе С++.


Это не важно. Важно то, что все эти фишки в языке реализованы. А что получается после компиляции: MSIL или native к непосредственно языку отношения имеет слабое.
Это важно. Это фичи не языка, а CLR. Которые программист получает вместе со всеми ее ограничениями. По сути дела(если не вдаваться в тонкости) это просто возможность писать CLR классы с использованием синтаксиса похожего на C++ и вызывать неуправляемый код.
Да, часть фич относятся скорее к рантайму (Reflection например). Но пример C++\CLI показывает, что и для C++ можно сделать рантайм, в котором будут работать такие фичи
Этот пример показывает, всего лишь, что c помощью определенного вмешательства в язык, можно сделать для него компилятор в .Net. Поверьте мне, C++ CLI выглядит как два языка в одном, и порой сообщаются они между собой весьма шероховато. С тем же успехом можно было впихнуть туда возможность компилирования специального вида классов в Java байт-код.
Но назвать это уместным видом развития языка я не могу, все-таки язык должен быть целостным, а то со временем захотят добавить еще функционально-ориентированную часть, часть без строгой типизации…
Этот пример показывает, всего лишь, что c помощью определенного вмешательства в язык, можно сделать для него компилятор в .Net


То есть на выходе мы имеем компилятор С++ с поддержкой всех фич, в качестве рантайма у которого в данном случае используется .NET
Неужели только MS под силу создать рантайм для C++, в котором могли бы существовать перечисленные фичи?
То есть на выходе мы имеем компилятор С++ с поддержкой всех фич, в качестве рантайма у которого в данном случае используется .NET

Рантайм .Net используется только для классов, объявленных специальным образом, весь код написанный на синтаксисе классического С++ компилируется так же, как и в обычном С++ компиляторе, и все плюшки для него недоступны.
Создание «антайм для C++, в котором могли бы существовать перечисленные фичи» для обычных С++ классов, с обеспечением обратной совместимости, по моему скромному мнению — задача очень сложно решаемая.
Рантайм .Net используется только для классов, объявленных специальным образом, весь код написанный на синтаксисе классического С++ компилируется так же, как и в обычном С++ компиляторе, и все плюшки для него недоступны.

Да. Но речь в данном случае идет о managed части C++\CLI

Создание «рантайм для C++, в котором могли бы существовать перечисленные фичи» для обычных С++ классов, с обеспечением обратной совместимости, по моему скромному мнению — задача очень сложно решаемая.

Конечно, обратной совместимостью придется пожертвовать. Но и хрен с ней, было бы о чем жалеть ;)
С первых слов Вашего комментария заинтересовался, неужели весь проект на C++/CLI, но к сожалению Вы немного противоречите сами себе =) Автор написал «на чистом C++/CLI», Вы частично не соглашаетесь, но в аргументации упоминаете тем не менее, что программу пишите и на C# :)

Я пытался в свое время писать целиком на C++/CLI, но пришел к выводу, что он действительно подходит только для связи управляемого кода с неуправляемым и оптимизаций. Потому что иначе проще писать либо целиком на C#, либо на C++.
В цитате у автора не сказано, что весь проект написан на C++ CLI, сказано, просто что новый проект. Поэтому я и привел пример наш проект, где около половины кода именно на нем.
В целом, GUI, бизнес-уровень нет смысла писать на С++ CLI, C# намного проще и выразительнее (меньше строчек кода, чтобы написать тоже самое). Не говоря уж, о том, что для C++ CLI нету даже дизайнера графических компонент.
у меня вообще ощущение что этот язык саботируют с какой-то неведомой целью. Действительно обидно что с 98го года, выхода предыдущего стандарта воз и ныне там.
Имхо вместо страхов боятся обратной совместимости давно пора было бы выпустить несовместимую версию языка, из которой убрать пару глупостей и добавить пару хороших вещей.
Если начать убирать разные глупости из С++ — можно получить совсем другой язык программирования.
давно пора было бы выпустить несовместимую версию языка, из которой убрать пару глупостей и добавить пару хороших вещей

… и получится какой-нибудь D, которым не пользуются преимущественно потому, что им не пользуются.
Пользуются D, просто не в таких объёмах, как C++. Сотни софта и библиотек же на C++ — так просто с этой иглы не слезть.
Когда выкидывают на мороз, всегда так.
Все эти фичи уместны в интерпретируемых языках с ООП типа Python, но здесь — уровень не тот. Если такое желание внести много плюшек в C++, сделали бы отдельный язык.

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

Концепции:
// много проще, понятнее и надёжнее написать

class Matrix(T) if( isNumeric!(T) )
{
....
}

чем
class Matrix<>
{
static_assert();
}

class Matrix { ... }

class Matrix { ... }

class Matrix { ... }

... и так далее


Модули:
Pimpl'ы в топку
Объявления friend классов не нужны (внутри модуля все поля доступны)
Просто меньше мороки с парами h/cpp.

Библиотека
кросплатформенно даже создать каталог нельзя. Любой более менее серьёзный проект начинается с создания обёрток над виндовыми и линуксовыми функциями.
Парсер все скобки повырезал. В оригинале было
class Matrix<>
{
static_assert();
}

class Matrix<int> { ... }

class Matrix<short> { ... }

class Matrix<unsigned int> { ... }

...
Я о том, что C++ — язык изначально не очень то для ООП. А «GUI, Math Special Functions, Networking, File System» в нём точно не нужны — кому надо, найдут библиотеки, а в язык та зачем толкать?!?
Вот здесь как раз коренное отличие от большинства интерпретируемых языков — в них мы пишем скрипты чтобы быстро выполнить задачу (для того и нужны «GUI, Functions, ...»), строить сверхмасштабируемые системы с масштабными концепциями (ООП). В компилируемом C++ мы наилучшим образом программируем конкретно саму машину.

Впрочем, времена и цели меняются, и вы разбираетесь в этом однозначно лучше меня. Так что вы, конечно, правы.
class Matrix(T) if( isNumeric!(T) )

Зачем оно нужно, когда можно написать:
template <typename T> class c1 {
	BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
};


Один из примеров, когда Boost спокойно справляется с задачей. А вот ответ компилятора на неправильный тип:
main.cpp: In instantiation of 'c1<void>':
main.cpp:13:11: instantiated from here
main.cpp:8:2: error: static assertion failed: «boost::is_arithmetic<T>::value»

И всё. И стоит оно сотни страниц стандарта?
Затем что можно легко создать две и более специализации класса:

class Matrix(T) if( isIntegral!(T) ) {}
class Matrix(T) if( isFloating!(T) ) {}


— Понятно что можно сделать тоже через прокси объекты, но мороки сколько, уж не говоря об «удовольствии» чтения такого кода.

Ну и более наглядно чем static_assert внутри класса.
Не более, чем синтаксический сахар:

#include "stdafx.h"
#include <type_traits>
 
template< class T, class EnableIf = void >
struct Matrix
{
    static_assert( !std::is_same< T, T >::value"Invalid T, must be integral or floating!" );
};
 
template< class T >
struct Matrix< T, typename std::enable_if< std::is_integral< T >::value >::type >
{
    void Who() const { std::cout << "I'm integral matrix!" << std::endl; }
};
 
template< class T >
struct Matrix< T, typename std::enable_if< std::is_floating_point< T >::value >::type >
{
    void Who() const { std::cout << "I'm floating point matrix!" << std::endl; }
};
 
int _tmain( int, _TCHAR*[] )
{
    Matrix< int >().Who();
    Matrix< double >().Who();
 
    // Generates error
    // Matrix< std::string >();
 
    return 0;
}
 
Тут надо объяснить, что Reflection, сборка мусора и остальные плюшки доступны только для managed классов (для тех, кто не знает в C++ CLI есть два типа классов — первый, который компилируется в MSIL и второй — который компилируется в нативный код) и традиционные возможности C++ расширяют слабо. Если вы пишете неуправляемый класс, то получаете не больше, чем в любом другом компиляторе С++.


Это не важно. Важно то, что все эти фишки в языке реализованы. А что получается после компиляции: MSIL или native к непосредственно языку отношения имеет слабое. Это скорее имеет отношение к рантайму.
За список невошедшего спасибо. А выводы какие-то сумбурные, прошу прощения. Microsoft не первый раз делает отсебятину, а потом все это бросает, кто-же согласится это за индустриальный стандарт принимать.
На самом деле непонятно зачем нормальный С++ превращать в кривой LISP (не в смысле что LISP кривой, LISP как раз в порядке ), кому надо динамический язык — на здоровье, хватает, в том числе и стандартизованных, а на С++ и так большинству программистов писать очень дорого и тяжело, а с этими прибамбасами боюсь ужас что начнется :)
Большего от C++/CLI и не требуется.
MS не бросает, а выжимает по-полной в течение несколько лет и переходит к новому. Как было с MFC. Так будет, вероятно, и с .NET
Ну Вы сравнили — обёртку над WinAPI на 2 десятка классов под 1 язык программирования и целую платформу, с кучей новых языков и концепций. Конечно, и время .NET когда-то пройдет, но вряд ли в ближайшее десятилетие.
да, MFC конечно в подметки не годится дотнету, но по значимости эти продукты сопоставимы. Вспомните конец 90х начало 00х. Собственно, единственной серьезной альтернативой MFC был борландовский VCL.
именно так — только бизнес мотивы нас в этом топике не интересует, бросили и все, это опасность любого проприетарного решения, могут бросить по любым причинам. я вот очень теперь волнуюсь за MySQL и Java — что теперь будет когда все в руках оракула.
По мне так уж модули куда важнее, кстати на маке с frameworks именно так и получается, а вообще надоело следить за соответствием заголовочных и библиотек.
Модули было бы приятно. Но с приличной фермой для распределённой компиляции ( а иначе в С++ и не жить ) — терпимо и без. А вот наличие концептов позволило бы делать темплейтные библиотеки дружественные к новичкам, что важно.
Куда более полезная фича — это рефлексия, кто юзает Qt меня понимают, там она есть, но было бы круче иметь её на уровне языка а не препроцессора!
a кто мешает использовать Qt для всяких раширений языка? я к примеру использую ядро игрового движка, для всего на свете :) там у меня и RTTI недорогой и делегирование и еще куча всего, что присуще динамическим языка, a вот с модулями я не видел решений кроме как на маке
Рефлексия в Qt — попытка выжать все что возможно из С++. Закономерно, получились костыли.
Если все эти фичи запилить и пожертвовать обратной совместимостью, то внезапно получится D!
вероятно. Но если у этого Ди — будет статус нового официального стандарта Си++ то внезапно на нем захочет писать код много людей — куда больше чем на Ди, так что будет надежда что он станет популярным.
Статья просто супер. Интересная тема и подача
занимало полторы сотни страниц (при том что весь остальной стандарт — около 800

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

В С++0х сборщика мусора не будет.

Не «не будет», а в стандарте определено как «зависит от реализации». Я не занудствую, это действительно разные вещи. И второе на данный момент намного лучше. По крайней мере до того момента, пока не формализуют условия существования мифического zero-cost garbage collector. Ну или не опровергнут проблему остановки =).

Thread pools, task launching, and reader-writer locks

Не забывайте, что в новом стандарте есть новая глава Threads на 50 страниц. Почти всё, что нужно программисту для multithread-программирования там есть.
Не знаю, откуда эта цифра, но у меня в финальном черновике 1338 страниц.

Из интервью с разработчиком майкрософтовского компилятора С++, не помню его имени, недавно оно пробегало на Хабре.

Не «не будет», а в стандарте определено как «зависит от реализации».

«Зависит от реализации» на практике означает, что писать код под сборщик мусора нельзя — потому как фиг его знает, каким компилятором он будет компилироваться и не стрельнет ли завтра разработчикам убрать уже даже написанный GC из компилятора.

Не забывайте, что в новом стандарте есть новая глава Threads на 50 страниц. Почти всё, что нужно программисту для multithread-программирования там есть.

Я упомянул об этом, а вообще статья о том чего нет, а не о том, что есть.
Т. е. вы считаете, что на чистом Си спокойно можно написать сборщик мусора boehm, а в C++ нельзя? A для кого в стандарте пишут, например, такое
In a garbage-collecting implementation, the fact that a region in an object is registered with declare_no_pointers() should not prevent the object from being collected.
А для чего там написаны разделы «20.6.4 Pointer safety» и «3.7.4.3 Safely-derived pointers»?
Сорри, Вы туда ответили?
Да, это относится к фразе «на практике означает, что писать код под сборщик мусора нельзя». Очевидно, что сборщик мусора тянет за собой рантайм, а за рантаймом всегда есть контроль со стороны программиста.
а как насчет того, чтобы объявить как deprecated все реализации строк, кроме одной и выдавать ошибки компиляции при использовании старой реализации? ;)
зачем?
есть разные реализации с разным профитом, где-то лучше одна, где-то другая.
Эх, а у них ведь могла отличная Java получиться :)
Справедливости ради хотелось бы упомянуть objective-c, который активно используется разработчиками под яблочные ОС.
В нём есть рефлексии, замыкания, сборщик мусора (говорят, целых два) и прочие плюшки. Из минусов — местами странный синтаксис и пониженная планка типобезопасности. А также нераспространённость на другие платформы.
Статья состоит сплошь из хороших новостей.
концепты и модули жалко.
все остальное не нужно.
С++ не тот язык где место детишкам привыкшим к GC и подобному сахару которого полно в том же шарпе. какой смысл делать еще один шарп?
Почитал я как-то «Джефф Элджер — C++ Библиотека программиста» и понял, что вряд ли стоит вносить в С++ что-то новое…
Вы еще Александреску «Современное проектирование на С++» почитайте ;)
Не, у Элджера экстримальнее все. Кто еще рассказывает о транзакциях, уплотнении памяти, сборке мусора и разного рода указателях в С++?
Поддерживаю все исключения, кроме концептов. Они, насколько я помню (в отличие от других «нововведений») уже побывали в одном из драфтов стандарта.
Рефлексию бы добавить, но сложно работать с ней будет.
UFO just landed and posted this here
GC реализован в С++\CLI отдельным ключевым словом gcnew. Никаких бездн и глубин не возникает.
Рефлексия — офигенная штука для плагинов, тестирования, моков и всяких финтов на рантайме.
UFO just landed and posted this here
На мой взгляд развитие C++ идет по пути Perl 6. Добавление множества write-only конструкций, которые, будучи написаны одним программистом не могут быть поняты и поддерживаемы другим.

Сделали бы только одну фичу — вывод понятных сообщений об ошибках хотя бы в STL, я уже не говорю про шаблоны в целом.
UFO just landed and posted this here
Да, если есть опыт прокручивания нескольких страниц одной ошибки, и поиска настоящей ошибки в середине текста. Если я допустил ошибку, так покажите мне первым делом мой код, а не потроха STL.
Сообщение об ошибке должно быть наиболее полным и информативным. Если у вас проблемы с чтением ошибок об инстанциации шаблонов — прикрутите себе STLFilt, делов то.

А ссылаться на то, что сложно понять код неопытному человеку это вообще по-моему не аргумент. В конце концов, пишите на Small Basic, там всё предельно просто.
С полнотой согласен, только в случае ошибок в темплейтных конструкциях (стл, буст, локи) вы получаете список наведённых ошибок, а это уже не камильфо. Одно дело когда чёрным по белому написано — ошибка в такой-то строке вашего файла, а далее, опционально, прицеплены все последствия этой ошибки и совсем другое — лоскут неудобочитаемого текста в котором ты сам должен найти первопричину. STLfilt это хорошо, но он работает только для стл-ошибок, а если я использую буст.мпл или ещё страшнее — буст.прото тогда как? И самое главное, что эту ситуацию кардинально никак не исправить не вмешиваясь в стандарт языка (концепции и были призваны это сделать).
вы получаете список наведённых ошибок, а это уже не камильфо. Одно дело когда чёрным по белому написано — ошибка в такой-то строке вашего файла, а далее, опционально, прицеплены все последствия этой ошибки
Так оно практически так и есть, за тем исключением, что ошибку надо искать в конце рядом со словами while instantiating template foo in source.cpp. А «наведенность» ошибок это из-за SFINAE.
STL это библиотека, в С я никогда не столкнусь с тем, что компилятор начнет изблевывать реализацию библиотеки, когда я допустил ошибку при ее использовании.
Спасибо за статью. Я поговорить о реализации Reflection в С++. В нем все хорошо, кроме того, что это не позволяет толком скрыть реализацию и, как ни крути, это все таки большой performance hit. Даже от введенных в какой-то из старых стандартов RTTI и dynamic_cast обычно стараются избавляться в продакшне. Ну и еще раз, я хочу подчеркнуть, что основной проблемой Reflection языков является их достаточно простая декомпиляция. Буквально на днях я «в рамках одной халтуры» разбирал несколько .NET сборок при помощи вот этой штуки www.reflector.net/ и результат меня с одной стороны порадовал, а с другой — просто шокировал.
Ну а разве с помощью дизасэмблера Вы сейчас не можете посмотреть в бинарном коде имена классов, функций, переменных и т.д.? Можете. Вот только сама программа эту информацию о себе получить не может. Т.е. защиты нет и сейчас (если не использовать отдельный упаковщик), а профита с этого никакого.
К счастью — нет. Если из бинарника выбрать всю debug info (в любом юниксе есть команда strip для этого) то вы не сможете восстановить из него ничего кроме логики работы, которая может быть крайне исковеркана при оптимизации. Не будут доступны не только имена переменных и классов но даже имена вызываемых функций, а о случаях с шаблонами и inline кодом и говорить нечего.
Можете провести эксперимент. Написать простейший пример на С++ (классы с наследованием, к примеру) и:
1. собрать:
g++ -O3 sample.cpp -o sample

2. посмотреть какой код будет в итоге собран на ассемблере:
g++ -O3 sample.cpp -S

3. проверить как это работает
./sample

4. попробовать дизассемблировать полученный бинарник, скажем, при помощи objdump-а, если вам все еще не хватило п.2
objdump -d sample >1

тут вы можете уже изучить дизасмеблированный код в файле «1» и найти его совершенно не пригодным для чтения, а так же заметить «следы имен» ваших переменных, функций и классов.

5. теперь чистим
strip -s samole

и повторяем п.4 — вот тут, я думаю, вы останетесь довольны. Обфускаторы и другая вселенская чушь были придуманы в тот же момент, когда появилась рефлексия в языках. С и С++ не нуждаются в них и фраза «сокрытие кода и реализации» тут — не пустой звук.
Sign up to leave a comment.

Articles