nums вписать в CSV таблицу в виде матрицы, то проще использовать функтор. Создать его, настроить поток вывода, символ-разделитель столбцов, количество выводов до перехода на следующую строку и передать в std::for_each.GetCursorPos[?] и ScreenToClient[?] чтобы на месте получить координаты курсора в клиентской области окна.D3DXVec3Unproject прямо из Wine. Там делается правильный и простой переход из пространства клиентской области окна в пространство области отсечения OpenGL через пространство вьюпорта.const char[N], где N - это размер памяти под строковой лиерал, в байтах.template< typename TValue >
void Foo( TValue& value ); // (1)Foo( "Hello" ); аргумент TValue определится как const char[6].template< typename TValue, size_t LENGTH >
void Foo( TValue (&value)[ LENGTH ] ); // (2)Foo( "Hello" );, аргумент TValue будет выведен как const char, а нетиповой аргумент LENGTH будет выведен в значение 6.template< typename TValue >
void Foo( TValue value );ибо вызывать функцию, которая определяет размер массива я собираюсь из другой функции, которая так же шаблонная и принимает массив (условно)неизвестного типа данных.
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aOffset;aOffset не должен быть uniform-ом. Это должен быть именно атрибут инстанса.#version 460 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aOffset;
void main()
{
gl_Position = vec4(aPos + aOffset, 0.0, 1.0);
}glVertexAttribDivisor[?].glVertexAttribDivisor( 1, 6 );.glm::vec2 translations[100].glm::vec2 translations[100];
int index = 0;
float offset = 0.1f;
for (int y = -10; y < 10; y += 2)
{
for (int x = -10; x < 10; x += 2)
{
glm::vec2 translation;
translation.x = (float)x / 10.0f + offset;
translation.y = (float)y / 10.0f + offset;
translations[index++] = translation;
}
}
glBindBuffer(GL_ARRAY_BUFFER, VBOs[3]);
glBufferData(GL_ARRAY_BUFFER, sizeof(translations), translations, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(glm::vec2), (GLvoid*)0);
glVertexAttribDivisor(1, 6);
glEnableVertexAttribArray(1);int правильно выбран в качестве типа для result.x + y работает только она.true всегда в таких случаях будет преобразован в 1 с типом int.x + y типом результата значения будет именно int, потому что ранг short int ниже ранга int в правилах продвижения. Арифметические операции с значениями всех типов, чей ранг ниже int, всегда подвергаются продвижению и выполняются на значениях с типом int.auto result в левой части выражения. Обобщение принимает тип результата выражения справа от знака равенства, коим и является int.Как я понимаю, эта техника позволяет писать перегрузку оператора внутри класса, как будто это член класса, а не глобальная бинарная дружественная функция.
friend std::ostream& operator<<(std::ostream& os, const Object & r) {/**/ return os;}operator << все так же остается глобальной функцией, определенной в том же пространстве имен, где определен и тип Object, но не в пространстве имен типа Object. Но, будучи определенным по месту объявления дружественности, оператор стал только ADL-доступным. Обращение к этому оператору может быть найдено только тогда, когда в конструкции std::cout << obj; этот obj имеет тип Object.Но почему такая же логика не работает с обычной функцией?
friend void fOUT (void) { }, опять же, является определением по месту объявления дружественности и доступна только через ADL. Но у нее нет аргументов чтобы ADL смог найти ее при обращении. Поэтому такая конструкция является бесполезной. GL_POLYGON предназначен для вывода только выпуклых многоугольников, а у тебя он выпуклым не является.GL_QUAD, или в режиме GL_TRIANGLES, явным образом выделяя отдельные квадратные участки.MyClass.h и MyClass.cpp. Когда нужно тематически разделить определение интерфейса, к имени класса после точки и перед расширением файла добавляется суффикс, говорящий о тематике определения. Например MyClass.serialization.cpp, MyClass.crud.cpp или MyClass.callbacks.cpp.template< size_t ROWS, size_t COLUMNS >
struct Matrix final
{
template< size_t R = ROWS, size_t C = COLUMNS >
inline std::enable_if_t<R == C, int> GetDeterminant() const
{
return 0;
}
};GetDeterminant не удалось вывести из шаблона? Будет ошибка трансляции, говорящая о том, что метод не найден. Это ничего не говорит пользователю. Это просто инструктирует транслятор остановить трансляцию. Пользователь, особенно если он не искушен знаниями о SFINAE, не сможет понять причину ошибки трансляции. Такая ситуация создаст риск излишней траты времени на дознание причин ошибки.template< size_t ROWS, size_t COLUMNS >
struct Matrix final
{
template< size_t R = ROWS, size_t C = COLUMNS >
inline std::enable_if_t<R != C, int> GetDeterminant() const = delete;
template< size_t R = ROWS, size_t C = COLUMNS >
inline std::enable_if_t<R == C, int> GetDeterminant() const
{
return 0;
}
};GetDeterminant.template< size_t ROWS, size_t COLUMNS >
struct Matrix final
{
inline int GetDeterminant() const
{
static_assert( ROWS == COLUMNS, "Matrix should be square to calculate the determinant." );
return 0;
}
};ArrayArray[0] = *new Array<int>{10};ArrayArray[0] вернет ссылку на Array<int>.*new Array<int>{10} выделяет память в куче под Array<int>, вызывает инициализатор Array<int>::Array(int length), после чего делает разыменование получившегося указателя на Array<int>.Array<int> будет выполнен оператор копирования по умолчанию, функциональность которого просто скопирует поля из объекта справа в объект слева от присвоения.new Array<int>{10} становится утекшим, т.к. указатель на него сразу становится потерян и освободить занимаемую им память становится невозможно.ArrayArray[0] = Array<int>{10};ArrayArray[0] вернет ссылку на Array<int>.Array<int>{10} инициализирует безымянный локальный объект на стеке, используя инициализатор Array<int>::Array(int length).T *m_data.ArrayArray[0] в этот момент начинает ссылаться на освобожденную память.ArrayArray в конце работы программы пытается удалить уже освобожденную память в ArrayArray[0].resize[?].insert[?].vertexBuffer.insert( vertexBuffer.begin() + 1, x );Только хотелось бы без специализации, чтобы код не дублировать
std::enable_if[?]. Часто его используют для выбора поведения шаблона исходя из черт аргумента шаблона.соответственно во всех методах, где этот член используется можно будет проверку if constexpr (someCondition)
if constexpr, нужно убирать в функции. А где эти функции лучше расположить? Верно - прямо там, где для их работы определены данные. Поэтому на самом деле if constexpr не нужен. Нужно определить набор функций с поведением там где оно возможно. А где нет - определить заглушки чтобы клиентский, относительно вариативного поведения, код не нуждался в проверках и мог просто обращаться к вариативному поведению так, как будто оно не вариативно и есть всегда.DebugName[?], в котором такие заглушки реализованы. *reinterpret_cast<T*>( &buffer[ sizeof( T ) * head ] ) = T{ std::forward<Args>( args )... };auto T vicar{ std::forward<Args>( args )... };
std::swap( *reinterpret_cast<T*>( &buffer[ sizeof( T ) * head ] ), vicar );std::swap, но только от людей со слабой привычкой пользоваться STL.T является неперемещаемым. В твоем ЦБ должны присутствовать проверки на перемещаемость, копируемость и возможность размена состояний.T можно копировать, но не перемещать, использовать стоит оператор копирования.T нельзя, следует пользоваться деструктором и размещающим конструктором.T включалась только одна конкретная перегрузка шаблона. .cpp обычно являются точками сборки модулей трансляции [?]..cpp подключить другой .cpp (исключенный из сборки иными способами), то все элементы с внутренним связыванием любого из этих .cpp будут доступны в них обоих..h. Файлы .cpp обычно включают .h и все вместе своим кодом формируют модуль трансляции, в котором доступны все элементы с внутренним связыванием. Даже в коде файлов .h.static) элементы именованных пространств имен по умолчанию имеют внешнее связывание [?]. Глобальное пространство является тоже именованным (и доступно через :: без имени слева) и ровно так же наделяет все свои нестатические элементы характеристикой внешнего связывания.inline.inline[?] дает пометку слабого внешнего связывания для любой сущности. Что константа или глобальная переменная, что функция или метод (даже статический), помечаются как сущности с внешним связыванием, которое не нарушает ODR в случае если все определения цели связывания во всех модулях трансляции являются полностью одинаковыми. Если хоть одно определение цели связывания отличается - будет нарушение ODR..cpp определить inline функции с одним именем и одной сигнатурой, но разными телами, то проблем со сборкой будет не избежать.