Страницы

Поиск по вопросам

Показаны сообщения с ярлыком стандарт. Показать все сообщения
Показаны сообщения с ярлыком стандарт. Показать все сообщения

суббота, 21 марта 2020 г.

Есть ли смысл использовать собственные реализации базовых АТД в C++?

#cpp #алгоритм #типы_данных #функциональное_программирование #стандарт


Задался вопросом, имеет ли смысл в настоящее время использовать собственные реализации
таких типов данных как связный список/стек/очередь/словарь? Именно для выполнения реальных
задач, а не в учебных целях. Казалось бы, стандарт языка С++ на данный момент предоставляет
большое количество инструментов, но несмотря на это, в некоторых проектах всё ещё продолжают
использовать самописные реализации тех или иных АТД. В том редком случае, когда стандартные
средства уступают в производительности самописным, логично, что выбор вряд ли будет
в пользу стандартных. Но в большинстве случаев нет какой-либо критичной разницы между
двумя подходами. Так стоит ли игра свеч?
    


Ответы

Ответ 1



Реализация контейнеров и алгоритмов в STL или Boost - веселая штука. Их делают максимально унифицированными (в основном для покрытия максимального кол-ва задач) и очень тщательно проверяют на быстродействие и т.д. Их пишут не один десяток людей, а ревьювят его вообще все ). Это дает гарантию что конкретная реализация будет максимально удовлетворять потребностям большинства. Время когда люди писали свои "общие" контейнера и алгоритмы наверное прошло. Но во в задачах (пример: Вам нужен произвольный доступ, и ассоциотивность) - да надо писать свой костыль. В стандартах очень много ассемблерных вставок для оптимизации производительности, и поэтому я не думаю что компилятор родит более вменяемый код, чем тот над которым посидели оптимизаторы. ИМХО: В реальных задачах надо брать готовое, а не рожать что-то (ибо дорого) сейчас вообще большинство ничего не кодит (дешевле найти готовое и пришить), что разумеется пичалька

среда, 29 января 2020 г.

Преобразование char -> int цифры и буквы

#cpp #c #стандарт #language_lawyer


Довольно часто в коде можно увидеть строки типа 

char cdigit = '8';
int idigit = cdigit - '0';


Реже, но также встречается

char letter = 'd';
int letter_number = letter - 'a';


Открываем Страуструпа "Язык прогрммирования С++" специальное издание, "Бином-Пресс",
2008. Цитата (стр 110):


  Небезопасно считать, ... что символы алфавита непрерывны (в стандарте EBCDIC между
i и j имеется разрыв)


У Кернигана и Ритчи вышеприведенный код (по крайней мере по цифрам) встречается регулярно.

Собственно вопрос по цифрам: обязательно ли корректен код idigit = cdigit - '0'?
    


Ответы

Ответ 1



В стандарте C++ §2.3/4 гласит: In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous. то есть В обоих наборе символов исходного текста и времени выполнения, значение каждого символа после 0 в приведённом выше списку десятичных цифр должно быть на единицу больше предыдущего. (перевод мой). Приведённый в §2.3/1 набор цифр таков: 0 1 2 3 4 5 6 7 8 9 Это гарантирует последовательность значений кодов цифр.

Ответ 2



Нашел всё-таки такую фразу в сишном Стандарте (C99): In both the source and execution basic character sets, the value of each character after0in the above list of decimal digits shall be one greater than the value of the previous.

вторник, 28 января 2020 г.

Почему ОТКРЫТАЯ функция из родительского класса становится недоступной в ОТКРЫТО унаследованном классе

#cpp #qt #gcc #компилятор #стандарт


если в производном классе имеется функция с тем же именем, но различной сигнатурой?

Пример.
Создаем класс TwoStageMap, открыто унаследованного от QMap:

template>
class TwoStageMap : public QMap
{
public:
    void insert(const F &fkey, const S &skey, const T &value1); //TODO: return an
iterator of what?

    void insert(const QPair &pair, const T &value1);

    T value(const F &fkey, const S &skey);

    T value(const QPair &pair);

};


При попытки обратиться к value() с сигнатурой из производного класса (TwoStageMap)
все прекрасно работает:

TwoStageMap> tsMap;

tsMap.insert(31, "October", "Halloween");
tsMap.insert(31, "December", "New Year's Eve");
tsMap.insert(25, "December", "Xmas");
tsMap.insert({25, "October"}, "Canna");

qDebug() << "Day1:" << tsMap.value1(31, "December");


, но как только попытаемся вызвать value() самого QMap (чтобы получить внутренний
контейнер под первым ключем), tsMap.value(31);, то тут же получаем ошибку:


  no matching member function for call to 'value'


При переименовании функции, например, в value1() проблема исчезает.
Вопрос - это ошибка компилятора или стандарт языка?
Компирятор gcc x86 64bit



Реализация класса, если кто хочет его использовать/попробовать:

template
void TwoStageMap::insert(const F &fkey, const S &skey, const T &value)
{
    Cont innerMap;
        if (QMap::contains(fkey)) {
            innerMap = QMap::value(fkey);
        }

    innerMap.insert(skey, value);
    QMap::insert(fkey, innerMap);

    //TODO: return an iterator of what?
}

template
void TwoStageMap::insert(const QPair &pair, const T &value)
{
    return insert(pair.first, pair.second, value);
}

template
T TwoStageMap::value(const F &fkey, const S &skey)
{
    auto innerMap = QMap::value(fkey);
    return innerMap.value(skey);
}

template
T TwoStageMap::value(const QPair &pair)
{
    return value1(pair.first, pair.second);
}




PS 
В примере Вызов функции_члена шаблонного базового класса из функции производного
шаблонного класса ситуация с невидимостью неквалифицированного имени функции шаблонного
родительского класса, с этим, как раз, вопросов нет, у меня, как можно видеть, идет
обращение через QMap::, здесь же немного другой случай, а именно, вопрос в
том, что мешает компилятору распознать перегружанную функцию с другой сигнатурой, используя
т.н. "искажение имен"? Если это стандарт языка, то вопрос, скорее к Комитету
    


Ответы

Ответ 1



При вызове метода класса по имени без квалификатора tsMap.value(31); для построения списка перегрузок будет осуществлен поиск имени без квалификатора в области видимости класса TwoStageMap согласно спецификации обращения к членам класса: 6.4.5 Class member access [basic.lookup.classref] 2 If the id-expression in a class member access (8.5.1.5) is an unqualified-id, and the type of the object expression is of a class type C , the unqualified-id is looked up in the scope of class C. Этот поиск будет завершен при нахождении имени value в классе TwoStageMap, так как поиск имени без квалификатора должен завершаться сразу при нахождении первого объявления, согласно спецификации поиска имени без квалификатора: 6.4.1 Unqualified name lookup [basic.lookup.unqual] 1 In all the cases listed in 6.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. Таким образом метод value из базового класса QMap в списке перегрузок будет отсутствовать. Чтобы это исправить можно Внести этот метод в область видимости класса TwoStageMap добавив using QMap::value; При вызове использовать имя с квалификатором: tsMap.QMap::value(31);

Ответ 2



Если я правильно понял проблему, то решается эта проблема с помощью using. #include #include class Base { public: void func(int _v) { std::cout << __FUNCTION__ << std::endl; } }; class Derived : public Base { public: using Base::func; void func(const std::string &_str) { std::cout << __FUNCTION__ << std::endl; } }; int main(int argc, char *argv[]) { Derived d; d.func("text"); d.func(1); return 0; }

Ответ 3



Не важно какой класс вы напишете. Допустим вы написали такой простой класс: class Your_class { protected: int n{ 3 }; public: int value(int n) const { return n + 3; } }; Если я наследую ваш класс, то я наследую все, что не является закрытым членами вашего класса: class My_class : public Your_class { }; В таком виде мой класс имеет функцию_член и обьект n вашего класса. Но как только я добавлю в класс: class My_class : public Your_class { public: bool value(const std::string& s) { return n == s.length(); } }; Этим я выражаю, что моя value это совсем другая функция(мне не нужен ваш вариант). И экземпляры моего класса не будут иметь возможность пользоваться одноименной функцией базового вашего класса. Для обеспечения этой возможности я смогу написать другую функцию, которая вызовит value вашего класса, или же сделать так, как описан в другом ответе. Точно также, если я добавляю в класс свой обьект n, то экземпляры моего класса будут пользоваться только этим обьектом. Так что, функция=член в производном классе с таким же именем, что и функция_ член в базовом, не является ее перегрузкой, а является ее заменой

вторник, 31 декабря 2019 г.

Кэширование лямбда-выражений C#

#c_sharp #стандарт #оптимизация #linq


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


Ответы

Ответ 1



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

Ответ 2



К ответу @VladD о JIT-компиляции добавлю, что похожее поведение можно наблюдать не только при обращении к обычным IEnumerable (Linq to Objects), но и в случае работы с Entity Framework. Однако в этом случае дело не в JIT-компиляции (хотя и она, разумеется, никуда не девается), а в так называемых "холодных запросах", во время которых "за кулисами" выполняется множество всяческих подготовительных действий по созданию и проверке моделей для дальнейшей работы с базой. После одного холодного запроса выполняются уже "горячие", которые происходят гораздо быстрее

Включает ли новый стандарт C++ в себя старый?

#cpp #cpp11 #cpp14 #cpp17 #стандарт


Вот есть c++11 и c++17, я могу писать в c++17 те вещи, которые можно писать в c++11?
То есть новый стандарт включает в себя старый?
    


Ответы

Ответ 1



Каждый стандарт С++ "включает" в себя предыдущие стандарты, т.е. в общем и целом обратно совместим с предыдущими стандартами. Но при этом могут иметь место несовместимости ("breaking changes"). Например сужающие преобразования были разрешены в {} инициализаторах в С++98/С++03, но запрещены в С++11. Также, каждый новый стандарт может окончательно удалять из языка те возможности, которые были признаны устаревшими/неприемлемыми ("deprecated") в предыдущих стандартах.

воскресенье, 22 декабря 2019 г.

Где взять POSIX стандарт?

#c #стандарт #posix


Хочу написать маленькую libc для своего микро-дистрибутива linux по POSIX стандарту,
после гугления я понял, что его принимает IEEE, если нет, то поправите меня, ибо я
не особо в этих стандартизациях разобрался.  

На сайте IEEE платный.  

Как писать по этому стандарту бесплатно, и где взять актуальную версию стандарта?
    


Ответы

Ответ 1



некоторые важные версии публикуются для свободного доступа на сайте организации the open group. например: The Single UNIX® Specification, Version 2 © 1997 The Open Group The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition © 2001-2004 The IEEE and The Open Group The Open Group Base Specifications Issue 7 IEEE Std 1003.1™, 2013 Edition © 2001-2013 The IEEE and The Open Group

среда, 11 декабря 2019 г.

Стандарт C++ на русском языке

#стандарт #cpp #cpp11


Еще один вопрос по C++ - можно ли где-то найти стандарт этого языка, переведенный
на русский? Читать полторы тысячи страниц (или сколько их там) на английском, к тому
же имея немалую вероятность многое неверно истолковать и перевести - мне это пока что
не под силу((    


Ответы

Ответ 1



Нет. Учите английский.

Ответ 2



Есть, Зуев Е. А., Чупринов А. А. "Стандарт С++: перевод, комментарии, примеры". Приобрести можно далеко не везде, цена тоже не слишком радует (от 3к). Если говорить о качестве перевода, то оно вполне достойное, сам автор оставил много комментариев.

понедельник, 1 апреля 2019 г.

Преобразование char -> int цифры и буквы

Довольно часто в коде можно увидеть строки типа
char cdigit = '8'; int idigit = cdigit - '0';
Реже, но также встречается
char letter = 'd'; int letter_number = letter - 'a';
Открываем Страуструпа "Язык прогрммирования С++" специальное издание, "Бином-Пресс", 2008. Цитата (стр 110):
Небезопасно считать, ... что символы алфавита непрерывны (в стандарте EBCDIC между i и j имеется разрыв)
У Кернигана и Ритчи вышеприведенный код (по крайней мере по цифрам) встречается регулярно.
Собственно вопрос по цифрам: обязательно ли корректен код idigit = cdigit - '0'?


Ответ

В стандарте C++ §2.3/4 гласит:
In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.
то есть
В обоих наборе символов исходного текста и времени выполнения, значение каждого символа после 0 в приведённом выше списку десятичных цифр должно быть на единицу больше предыдущего.
(перевод мой). Приведённый в §2.3/1 набор цифр таков:
0 1 2 3 4 5 6 7 8 9
Это гарантирует последовательность значений кодов цифр.

суббота, 29 декабря 2018 г.

Кэширование лямбда-выражений C#

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


Ответ

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

вторник, 13 ноября 2018 г.

Где взять POSIX стандарт?

Хочу написать маленькую libc для своего микро-дистрибутива linux по POSIX стандарту, после гугления я понял, что его принимает IEEE, если нет, то поправите меня, ибо я не особо в этих стандартизациях разобрался.
На сайте IEEE платный.
Как писать по этому стандарту бесплатно, и где взять актуальную версию стандарта?


Ответ

некоторые важные версии публикуются для свободного доступа на сайте организации the open group
например:
The Single UNIX® Specification, Version 2 © 1997 The Open Group The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition © 2001-2004 The IEEE and The Open Group The Open Group Base Specifications Issue 7 IEEE Std 1003.1™, 2013 Edition © 2001-2013 The IEEE and The Open Group

вторник, 9 октября 2018 г.

Какой смысл в символе “Т” в стандартном формате записи даты-времени?

Какой смысл в символе "Т", например, вот в такой записи даты/времени: 2017-12-27T12:59:04.723 ?


Ответ

Символ T - это разделитель даты и времени в строке, описывающий время. Определён в стандарте ISO 8601. См. раздел Combined date and time representations