MavyPOP•

Play with it on godbolt

Ex2 - make it looks more native C++ on godbolt

By returning a closure lambda around the input parameter packs, we can construct a compile-time equivalent of GLSL's vector swizzling. Try changing the size and order of the vector elements x,y,z,w on line 167 (line 210 on Ex2) and see that you get the exact type.

This works on Clang and GCC but MSVC doesn't seem to enable this behavior/abuse.

EDIT: thanks to u/dodheim for pointing out the extension warning from Clang is precisely why it doesn't work at all for MSVC: this "trick" is a GNU extension of the language. Still, in those environments can be quite useful but not portable.

2
dodheim•

This works on Clang and GCC but MSVC doesn't seem to enable this behavior/abuse.

If you build your example with Clang (trunk), it emits "warning: string literal operator templates are a GNU extension [-Wgnu-string-literal-operator-template]", so this will warn/error when using -pedantic as well. C++20's NTTPs should allow the same functionality, I think, though with yet another different syntax.

2
MavyPOP•

Good point about `-pedantic`.

I'm curious if MSVC will allow templates for the literal operator at all in C++20. Currently it refuses to allow you to

2
dodheim•

MSVC supports numeric literal operator templates just fine, which prior to C++20 were the only valid literal operator templates. C++20 adds support for string literal operator templates via NTTPs, but I don't think MSVC supports NTTPs at all yet.

4
MavyPOP•

If you toggle the compiler in my godbolt links to MSVC, it says that the literal op cannot be templated and must instead provide (const char* str, size_t len) as the function arguments. So if I understand correctly, MSVC handles templated literal ops only if it's numerical. In my example case template<typename CharT, CharT... chars> has {CharT = char } which is not and so it rejects it.

1
johannes1971•

How is the use of _swizzle as a user-defined literal any better than just having a function swizzle (vec4, "zyxw")?

2
MavyPOP•

The input string must be a constant expression in order to get the expected vector values and correct result size at compile time.

7
emdeka87•

For vec4 there aren't too terribly many permutations of x,y,z,w. Why not just create a method for each?

1
MavyPOP•

any element can be repeatable which means for a set of (x,y,z,w) you'd need 256 methods. This code is much shorter and can allow different sets of swizzling characters like (r,g,b,a) and (s,t,p,q). If you were to support those characters like GLSL, you'd need 512 more implementations. Alternatively, that's just 8 more character checks in the if constexpr statements with no additional functions.

3
emdeka87•

Oh k didn't think about the repeating, nvm

1
NamalB•

https://godbolt.org/z/D2fzAZ I like the syntax, vec4.get<_x, _y, _z, 1>(); In this you can add arithmetic values in the swizzle as well. Following will give you a compile error because there is no 'z' component in vec2, vec2.get<_x, _z, _z>();

0
_lichtbogen_•

I like that syntax a lot more!

"xxyz".swizzle(vec) doesn't read as "natural" C++ code imho.

1
MavyPOP•

Ex2 that I linked in both the github repo and top comment shows you how to make it look more natural with
vec.swizzle(xxyz)

https://godbolt.org/z/z45Ug8

1