#c #gcc #macros #preprocessor
Вопрос:
Позвольте мне начать этот вопрос с того, что я не знаю, возможно ли то, что я собираюсь сделать, и если да, то я не знаю, как найти информацию.
Язык затенения OpenGL допускает синтаксис, называемый swizzeling.
Если у кого-то есть вектор
v {x, y, z}
можно построить новый вектор, выполнив
v.xxx, v.xxy, v.xxz, v.xyx, ... etc
Существует в общей сложности 3 * 3 * 3 = 27 возможных вариантов.
Я хотел бы реализовать такую функцию в своей собственной векторной библиотеке.
Вот один из примеров такой функции:
vec3<T> xxx() const
{
vec3<T> v(x, x, x);
return v;
}
Затем я мог бы написать еще 26 функций для учета всех возможных вариантов, но это похоже на то, что я должен уметь делать с помощью макроса. Например, что-то вроде
vec3<T> (#A)(#B)(#C)() const
{
vec3<T> v(#A, #B, #C);
return v;
}
где #A, #B и #C-это 3 одиночных символа , которые компилятор расширяет возможными вариантами x
, y
и z
.
Возможно ли такое с gcc/g ?
Комментарии:
1. вместо того, чтобы спрашивать «возможно ли это», лучше опишите, что пошло не так, почему вы пытались это реализовать. Ответ на вопрос, который вы сейчас задаете, — «Да».
2. @463035818_is_not_a_number Я прочитал несколько страниц, связанных здесь, ни одна из которых не содержала никакой информации, которую, как я думал, я мог бы адаптировать для выполнения того, что я собираюсь сделать gcc.gnu.org/onlinedocs/cpp/Macros.html
3. Вы, конечно, могли бы использовать макрос, чтобы свести к минимуму количество дублирования кода, но я думаю, что вам все равно придется прописывать каждую перестановку
xyz
вручную. Таким образом, вместо 27 пятистрочных функций вы видите макрос из пяти/шести строк и 27 вызовов. Я надеюсь, что вам не нужно распространять это на вектор4…4. @TimRandall — все равно это большое улучшение, как это можно реализовать?
5. Две вещи: OpenGL фактически определяет вращение для 4D векторов (x, y, z и w). И если вы хотите сделать это на C , проверьте glm, он уже делает это, и это де-факто библиотека C/C для OpenGL/Vulkan math.
Ответ №1:
#define SWIZZLE(a,b,c)
vec3<T> a##b##c() const
{
vec3<T> v(a, b, c);
return v;
}
SWIZZLE(x,x,y)
SWIZZLE(x,x,y)
SWIZZLE(x,x,z)
...
Для получения дополнительной информации об ##
операторе найдите «вставка токенов».
Комментарии:
1. Интересно, что такое double
##
— что я должен искать, чтобы найти дополнительную информацию о том, что это такое / как это работает с препроцессором?
Ответ №2:
Вы можете определить
#define make_method(x,y,z) vec3<T> x##y##z () const { return { x , y, z}; }
Такой, что
make_method(a,b,c)
расширяется до
vec3<T> abc () const { return { a , b, c}; }
Теперь вам просто нужно перечислить все 27 комбинаций, подобных этой:
make_method(x,x,x);
make_method(x,x,y);
make_method(x,x,z);
make_method(x,y,x);
// ....