__stdcall обязывает пользователя функции передать параметры функции на стеке по значению, но освобождает его чистить стек после вызова. Стек от параметров чистит сама вызванная функция.BOOL (__stdcall *)(HANDLE, PBOOL) на bool (__stdcall *)(void*, bool*) компилятор думает об одном размере стека, а код функции - о других.__stdcall свой результат передает через регистр. регистр используется целочисленный или вещественный. Для целочисленного регистра используется правило продвижения типа. Это означает, что функция, записав значение типа BOOL (размер 4Б) ничего не испортит пользовательскому коду, который прочитает из регистра все 4Б с учетом правила продвижения.bool*) передается в использование как указатель на четырехбайтовое целое (BOOL* или PBOOL). Вызываемая функция ведь имеет сигнатуру BOOL (__stdcall *)(HANDLE, PBOOL) и со вторым параметром работает как с 4Б целым по указателю.isWow64 и был поломан в результате вызова IsWow64Process с параметром неподходящей длины. Измени тип isWow64 на BOOL и все станет нормально, даже хендл "kernel32.dll" потом сможешь нормально освободить. glDrawElements). С точки зрения шейдера, материал - это комплекс из программы шейдера и набора входных/выходных параметров этой программы.class a final
{
private:
class ex
{
int f = 0;
};
static void foo() { std::cout << 'f' << std::endl; };
public:
class F
{
public:
F() { foo(); };
private:
ex m_exes[4];
};
}; state ? (cout << b / a << endl, exit(0)) : state = (a == 0) && (b == 0);exit(0) или конструкцию присвоения внутри тернарного оператора.: накладываются некоторые ограничения. Если выражения не проходят по ограничениям тернарного оператора, выражение тернарного оператора считается плохо сформированным, что и приводит к ошибке синтаксиса. void display()
{
glClear( GL_COLOR_BUFFER_BIT );
glBegin( GL_LINE_LOOP );
for( size_t index = 0; index < vertices.size(); ++index )
{
const Vertex& vertex = vertices[ ( index * 3 ) % vertices.size() ];
glVertex2i( vertex.x, vertex.y );
}
glEnd();
glFlush();
} std::initializer_list участвует в двух из трех.Foo bar = {...};
Foo bar{...};std::initializer_list выполняются только на этапе трансляции. В обоих случаях сперва транслятор попробует придумать std::initializer_list. Если у аргументов типы разные (а приведение типов при такой записи не делается), то попробовать создать std::initializer_list у транслятора не получится. Но если получилось, то транслятор уже итак знает число аргументов, переданных в конструктор.std::initializer_list, с которым конструктор и вызывается.std::initializer_list нельзя копировать, перемещать, сохранять в состоянии конструируемого объекта. std::initializer_list не владеет отображаемой памятью, он только дает к ней доступ. s = loc::get("key"); // ambiguous overload for op=std::wstring (конструктор копирования и конструктор преобразования из const wchar_t*) являются неявными.TaggedCWstr так же являются неявными.std::wstring_view.std::wstring и этим позволять бесконтрольно обращаться к динамической памяти без явного понимания этого процесса. Лучше для получения std::wstring сделать operator *, а еще лучше - вообще не ломать семантику операторов и сделать метод с говорящим именем. std::auto_ptrявляется устаревшим и удален из стандартной библиотеки начиная со стандарта C++17.std::unique_ptr.std::auto_ptr мог следить только за памятью одного экземпляра. Передать туда память массива можно, но деструктор будет вызван только у первого экземпляра массива. В общем смысле это означает утечку памяти.std::unique_ptr, наоборот, способен контролировать память как единичного экземпляра, так и массива экземпляров. Еще в отличии от своего устаревшего товарища, std::unique_ptr способен спокойно передавать свое состояние, не создавая возможность двойного освобождения памяти. В дополнение, std::unique_ptr еще способен пользоваться нестандартными деструкторами, что очень кстати при работе, например, с COM-объектами или нестандартной схемой аллокации памяти.main.void swap(T& first, T& second).std::swap.template <typename T1>
void out_array(const T1* array, size_t arraySize)arraySize тоже не нужен. Ты работаешь с сырыми массивами фиксированной длины и можешь дать своему шаблону функции понимание длины такого массива. Делается это так.template < typename TElementType, size_t LENGTH >
void out_array( const TElementType array[ LENGTH ] )char array2[n] = { '2','1','4','5','3','-3','-1','-2','-4','-5' };'2' не будет эквивалентно 2. С этого момента сортировка будет сортировать по коду символьной таблицы, а не по значению числа. Это ошибка, т.к. это явно не то поведение, которое ты ждешь.'-3' и.т.д. Тип у такой конструкции будет int, а не char. Компилятор тебе именно об этом и пытается сказать.int array3[n] = atoi(array2);int array3[n];
std::transform(
std::begin( array2 ), std::end( array2 ), std::begin( array3 ),
[]( const char item ) -> int { return item; }
);std::transform. Node root = {T{}, nullptr, nullptr};Node root{T{}, nullptr, nullptr};template <typename T>
struct NameOf {};NameOf. Определение это я сразу назову неправильным, потому что от этого шаблона можно инстанцировать тип и получить совершенно непонятную ошибку компиляции дальше. Должно быть так, чтобы тип из общей формы шаблона инстанцировать было нельзя.#define DEF_TYPENAME(type) template <> \
struct NameOf<type> {\
static const char value[];\
};\
const char NameOf<type>::value[] = #type;NameOf для переданного типа. Тут я скажу только то, что можно сделать полностью иначе и макрос тут полностью не нужен.DEF_TYPENAME(int)
DEF_TYPENAME(double)
DEF_TYPENAME(long double)
DEF_TYPENAME(float)
DEF_TYPENAME(char)
DEF_TYPENAME(long)
DEF_TYPENAME(unsigned)
DEF_TYPENAME(unsigned long); все таки был бы более уместен в этом месте, т.к. сейчас код выглядит несвязной простыней без структуры. Сразу хочется сказать что тут синтаксическая ошибка, хоть на самом деле это и не так.NameOf.template <typename T, typename ...types>
void printTypes(T)
{
std::cout << NameOf<T>::value << std::endl;
}
template <typename T, typename ...types>
void printTypes(T, types... t)
{
std::cout << NameOf<T>::value << ", ";
printTypes(t...);
}printTypes из шаблона. Я сейчас остановлюсь лишь на второй ветви вывода.template <typename T, typename ...types>
void printTypes(T, types... t)
{
std::cout << NameOf<T>::value << ", ";
printTypes(t...);
}typename ...types в объявлении шаблона говорит что типов ожидается от нуля и пока фантазия не кончится. Как пользоваться таким шаблонами - хорошо описано в документации по моей ссылке.std::cout << NameOf<T>::value << std::endl;. ::new является точкой обращения к аллокатору памяти процесса. К какому именно аллокатору идет обращение - как правило неизвестно. Это может быть dlmalloc, mimalloc или jemalloc. Их много и перечислять можно долго. Это может быть и самостоятельно созданный по мотивам доклада Александреску аллокатор.::delete). IMagicSpell::ShowDebugInfo у тебя обращается к приватному полю IMagicSpell::SpellInfo. Это поле недоступно для наследников, т.к. является приватным.Fireball::Fireball, у тебя работает с приватным полем Fireball::SpellInfo.IMagicSpell::SpellInfo и Fireball::SpellInfo являются разными, расположены в разных областях памяти объекта Fireball и в принципе никак не могут пересечься своими данными.Fireball будет с два MagicSpellInfo плюс размер таблицы виртуальных символов.MagicSpellInfo в иерархии - лишний. Fireball::SpellInfo является дублирующим, лишним полем, которое не позволяет добиться необходимой тебе функциональности. Ведь в обоих твоих классах тебе надо работать с одними данными, с полем IMagicSpell::SpellInfo.Fireball::SpellInfo.class Fireball: public IMagicSpell {
public:
Fireball() {
SpellInfo.Name = "Огненный шар";
SpellInfo.Description = "Мощный огненный шар, сметающий все на своем пути.";
SpellInfo.Type = fire;
SpellInfo.MinDamage = 30;
SpellInfo.MaxDamage = 50;
SpellInfo.Range = 40;
SpellInfo.Distance = 120;
}
virtual ~Fireball() {}
virtual void Use() {
cout << "Boom!" << endl;
}
};IMagicSpell::SpellInfo является приватным и недоступен для потомков. Исправить это тоже очень легко. private - приватный доступ, только для экземпляра текущего класса;protected - ограниченный доступ, только для экземпляров текущего класса и всех публичных наследников; доступ ограничивается при ограниченном или приватном наследовании;public - публичный доступ, для всех пользователей экземпляров класса.IMagicSpell::SpellInfo с приватного на ограниченный. В этом случае экземпляры Fireball смогут обращаться к IMagicSpell::SpellInfo как к своему ограниченному полю.class IMagicSpell {
protected:
MagicSpellInfo SpellInfo;
public:
virtual ~IMagicSpell() {}
virtual void Use() {}
MagicSpellInfo GetInfo() {
return this->SpellInfo;
}
void ShowDebugInfo() {
cout << "Название: " << SpellInfo.Name << endl;
cout << "Описание: " << SpellInfo.Description << endl;
cout << "Тип: " << SpellInfo.Type << endl;
cout << "Мин. урон: " << SpellInfo.MinDamage << endl;
cout << "Макс. урон: " << SpellInfo.MaxDamage << endl;
cout << "Расстояние: " << SpellInfo.Distance << endl;
cout << "Радиус: " << SpellInfo.Range << endl;
}
};get_substr("один", "два три четыре"), ты в функцию передаешь два строковых литерала, тип которых - const char[ N ], где N - это длина строки литерала включая терминальный символ '\0'.const char* в char* недопустимо, поэтому компилятор и пишет тебе ошибку.char* вообще не нужен, т.к. полностью все операции у тебя не приводят к изменению состояния строки. Заменить char* на const char* будет и логичнее, и понимаемость кода тоже улучшит. debug и принимает аргумент, но вне отладочной конфигурации он этим аргументом не оперирует. В любом месте обращения к твоему макросу произойдет подстановка NULL вместо всего обращения.NULL в качестве подстановки не нужен. Зачем тебе в коде программы обилие висящих NULL? Если описать макрос так:#ifdef DEBUG
#define debug(n) Serial.println("***"+String(n)+"***")
#else
#define debug(n)
#endifoperator<<(ofstream&, const Book&) должен быть определен в пространстве имен std, т.к. ofstreamопределен именно в этом пространстве.namespace std
{
// use the `Book` type definitely from global namespace.
ofstream& operator<<(ofstream &of, const ::Book &book)
{
// ...
}
}И еще вопрос: что нужно возвращать из этой функции?