Я люблю запрыгивать в ветки о С++ и набрасывать, что оный не нужон. Но на самом деле я всегда внимательно изучаю любой инструмент, потому что люблю эффективную работу и экономию ресурсов. Так сложилось, что за всё время мне не попадался проект, который бы раскрыл С++ как уникальный язык. Адепты часто любят приводить пример с сортировкой, мол, только в С++ можно вставить функцию сравнения непосредственно в тело сортировки (умалчивая, правда, что от каждой такой вставки бинарник жиреет как боров), а в остальных языках приходится довольствоваться компараторами. Ну ещё про возможность отключения виртуальной таблицы я слышал, хотя в Java уже давно присутствует devirtualization. Ну и другие какие-то микрооптимизации под лозунгами "not pay for what you not use".
Теперь без шуток. Вы можете привести примеры проектов, которые действительно раскрывают способности С++1x? Не холивара ради, а для самообразования. Меня по большей части интересует defensive programming и метапрограммирование, потому что прирост производительности на 20% звучит круто, но в наше время нафиг никому не нужен, потому что пользователи спокойно терпят мобильные приложения под гигабайт, которые вечно тупят, и веб-страницы размером с дистибутив Windows 95. А вот возможность кратно уменьшить количество ошибок в проекте 1М LoC — дорогого стоит. Но и на любые другие проявления тоже будет интересно посмотреть.
Здравствуйте, cppguard, Вы писали:
C>Адепты часто любят приводить пример с сортировкой, мол, только в С++ можно вставить функцию сравнения непосредственно в тело сортировки (умалчивая, правда, что от каждой такой вставки бинарник жиреет как боров), а в остальных языках приходится довольствоваться компараторами.
Да нет, такое даже в .NET будет работать при определённых условиях. Правда, нужно брать достаточно новые версии API, где компаратаор передаётся не по старинке как интерфейс IComparer<T> (динамический run-time полиморфизм), а как параметр дженерика с констрейнтом TComparer where TComparer : IComparer<T> (статический полиморфизм, мономорфизация на этапе JIT-компиляции):
public static void Sort<T, TComparer>(this Span<T> span, TComparer comparer)
where TComparer : IComparer<T>?
Здравствуйте, Qbit86, Вы писали:
Q>Да нет, такое даже в .NET будет работать при определённых условиях. Правда, нужно брать достаточно новые версии API
Где брать? Руками такое наколбасить на раз можно, хотелось бы увидеть достаточно новые версии именно API.
Здравствуйте, samius, Вы писали:
S>Руками такое наколбасить на раз можно, хотелось бы увидеть достаточно новые версии именно API.
См., например, Sort() и BinarySearch() для Span'ов [1]
S>Где брать?
Я когда-то, когда увидел эти API, искал компараторы по исходникам BCL [2], что ещё есть похожего, и куда ещё такой подход внедряют.
Потому что такой подход для BCL всё же нетипичен, там издревле использовался OOP-Java-style вместо constrained generics для передачи компараторов и прочих стратегий/политик.
Но, емнип, там особенно ничего не было за пределами этих API для Span'ов.
Здравствуйте, cppguard, Вы писали:
C>Меня по большей части интересует defensive programming и метапрограммирование
вот лично по-моему мнению C++ может дать фору в безопасности любому языку с GC и общим наследником в виде Object.
Задавал недавно вопрос, как реализовать новый тип в .Net ветке.
Все решения мягко говоря многословны. И заставляет каждый тип реализовывать чуть ли не в отдельном файле.
В С++ это реализуется куда проще.
Общий класс:
struct CityDim;
using City = NewType<std::string, CityDim>;
struct CountryDim;
using Country = NewType<std::string, CountryDim>;
struct CountryInfo{};
std::optional<CountryInfo> findCountry(const Country& c) {
return std::nullopt;
}
int main()
{
auto city = City{"Moskow"};
auto country = Country{"Russia"};
findCountry(city); // выдаст ошибку на этапе компиляции
}
Сразу можно вспомнить библиотеку boost::units. Аналоги есть конечно и на других языках, но они менее универсальны.
Ещё можно вспомнить такую либу как gsl и тип not_null. Такой реализовать на java/C# тяжело. Какое-то подобие ввели в виде оператора !! в C#. Но оно всё равно не то.
Конечно Rust в данном случае оставляем за скобками. Но то отдельная тема. Смотрим только на мейнстрим.
Здравствуйте, sergii.p, Вы писали: SP>Задавал недавно вопрос, как реализовать новый тип в .Net ветке.
Хм, и я тебе там дал пример... SP>Все решения мягко говоря многословны. И заставляет каждый тип реализовывать чуть ли не в отдельном файле. SP>В С++ это реализуется куда проще.
using System;
using City = NewType<string, CityDim>;
using Country = NewType<string, CountryDim>;
public struct CityDim {}
public struct CountryDim {}
struct CountryInfo{};
public struct NewType<TIdentifier, TTag> : IComparable<NewType<TIdentifier, TTag>>, IEquatable<NewType<TIdentifier, TTag>>
where TIdentifier : IComparable<TIdentifier>, IEquatable<TIdentifier>
{
private TIdentifier _value;
public NewType(TIdentifier value)
{
_value = value;
}
public TIdentifier Value
{
get { return _value; }
}
public override string ToString()
{
return _value.ToString();
}
public override bool Equals(object obj)
{
if (obj is NewType<TIdentifier, TTag>)
{
var other = (NewType<TIdentifier, TTag>) obj;
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
return _value.GetHashCode();
}
public bool Equals(NewType<TIdentifier, TTag> other)
{
return _value.Equals(other.Value);
}
public int CompareTo(NewType<TIdentifier, TTag> other)
{
return _value.CompareTo(other.Value);
}
public static bool operator== (NewType<TIdentifier, TTag> id1, NewType<TIdentifier, TTag> id2)
{
return id1.Equals(id2);
}
public static bool operator != (NewType<TIdentifier, TTag> id1, NewType<TIdentifier, TTag> id2)
{
return !id1.Equals(id2);
}
}
public class Program
{
static CountryInfo? findCountry(Country c) {
return null;
}
public static void Main()
{
var city = new City("Moskow");
var country = new Country("Russia");
findCountry(country); // ok
//findCountry(city); // выдаст ошибку на этапе компиляции
//Console.WriteLine("Are equals: {0}", city == country); // выдаст ошибку на этапе компиляцииvar city2 = new City("Moskow");
Console.WriteLine("Are equals: {0}", city == city2);
}
}
SP>struct CityDim;
SP>using City = NewType<std::string, CityDim>;
SP>struct CountryDim;
SP>using Country = NewType<std::string, CountryDim>;
SP>struct CountryInfo{};
SP>std::optional<CountryInfo> findCountry(const Country& c) {
SP> return std::nullopt;
SP>}
SP>int main()
SP>{
SP> auto city = City{"Moskow"};
SP> auto country = Country{"Russia"};
SP> findCountry(city); // выдаст ошибку на этапе компиляции
SP>}
SP>
Как это делается на современном C#
CountryInfo? findCountry(in Country c) {
return null;
}
struct CountryInfo{}
public record struct City(string Name);
public record struct Country (string Name);
SP>Ещё можно вспомнить такую либу как gsl и тип not_null. Такой реализовать на java/C# тяжело. Какое-то подобие ввели в виде оператора !! в C#. Но оно всё равно не то.
Очень даже то. В коде выше ты не можешь передать null в конструктор City, хотя string это ссылочный тип.
SP>Конечно Rust в данном случае оставляем за скобками. Но то отдельная тема. Смотрим только на мейнстрим.
Раст примерно на уровне C#, только derive макрос надо написать
Здравствуйте, cppguard, Вы писали:
C>Теперь без шуток. Вы можете привести примеры проектов, которые действительно раскрывают способности С++1x? Не холивара ради, а для самообразования. Меня по большей части интересует defensive programming и метапрограммирование, потому что прирост производительности на 20% звучит круто, но в наше время нафиг никому не нужен.
Очевидный вывод — C++ не про стабильные приложения и не про метапрограммирование. Помимо игровых движков, есть любители (и профессионалы) писать серверные приложения на С++ — т.к. экономия цпу и памяти в плюсовых приложениях выливается в серьезную экономию трат на сервера.
Здравствуйте, LuciferSaratov, Вы писали:
LS>Игроделам нужен, современные ААА-тайтлы это С++ (за редчайшими исключениями, с которыми тоже не все так однозначно).
С игроделами всё сложно, потому что они уже давно завязаны на консоли, которые до последнего времени можно было отнести к embedded platforms со всеми вытекающими.
C>прирост производительности на 20% звучит круто, но в наше время нафиг никому не нужен
Спроси любого владельца бизнеса, хотел бы он уменьшение расходов на 20%?
C>А вот возможность кратно уменьшить количество ошибок в проекте 1М LoC — дорогого стоит
А ведь можно подойти иначе: критичную часть оптимизируем на плюсах, а бОльшую часть, подверженную ошибкам, пишем на любом другом языке, который вы сочтете более безопасным.
Ну и как выше уже писали: есть ряд областей, где не то, что 20%, где 5% уже будет успехом и конкурентным преимуществом.
Здравствуйте, cppguard, Вы писали:
C>С игроделами всё сложно, потому что они уже давно завязаны на консоли, которые до последнего времени можно было отнести к embedded platforms со всеми вытекающими.
Консоли от embedded-подхода ушли очень давно, на всех консолях уже больше 15 лет как операционные системы.
Здравствуйте, cppguard, Вы писали:
C>С игроделами всё сложно, потому что они уже давно завязаны на консоли, которые до последнего времени
Ещё в мою бытность геймдевелоперства консоли перестали быть embedded.
Здравствуйте, DiPaolo, Вы писали:
C>>прирост производительности на 20% звучит круто, но в наше время нафиг никому не нужен DP>Спроси любого владельца бизнеса, хотел бы он уменьшение расходов на 20%?
Это будет глупый вопрос. "Хотите снизить расходы на 20%"? — Да!, "а если для этого нужно нанять вместо команды java-среднячков С++-экспертов за офердофига"? — э...
Здравствуйте, CreatorCray, Вы писали:
C>>С игроделами всё сложно, потому что они уже давно завязаны на консоли, которые до последнего времени CC>Ещё в мою бытность геймдевелоперства консоли перестали быть embedded.
Напомни, в каком поколении приставок добавили возможность увеличивать RAM, менять CPU и GPU?
Здравствуйте, CreatorCray, Вы писали:
CC>Вон у меня есть лапотоп, в котором это всё распаяно и поменять можно разишо только на заводе. CC>По твоему это embedded?
An embedded system is a computer system—a combination of a computer processor, computer memory, and input/output peripheral devices—that has a dedicated function within a larger mechanical or electronic system.
То есть, если некто криаторкрэй стал настольк оплатежеспособным, что под его ноут кто-то целенаправленно решил выпускать ПО, то таки да. Ну и компания здорового человека делает так, что ПО под целевую платформу не тормозит, не лагает и чувствует себя вполне нативненько. В этом и есть особенность embedded, по моему мнению. Этот же параметр делает Android, сюрприз-сюрприз!, НЕ embedded платформой, потому что ресурсы в общем случаи неизвестны, и современные разработчики тупо ориентируются на флагманы.