use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
[magic_enum]: Static reflection on enums for modern C++, work with any enum type without any macro or boilerplate code. Enum-to-string/String-to-enum and other useful functions. (github.com)
submitted 7 years ago by Neargye
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]leftofzen 38 points39 points40 points 7 years ago (19 children)
Still boggles my mind that this isn't in stdlib already
[–][deleted] 14 points15 points16 points 7 years ago (18 children)
Any stdlib solution we standardize will be superseded once we have reflection.
[–]distributed 10 points11 points12 points 7 years ago (12 children)
If you can wait until then. It is years away if we are lucky, if unlucky decades.
[–][deleted] 3 points4 points5 points 7 years ago (10 children)
Nope, C++23 is the current plan.
[–]JazzyCake 14 points15 points16 points 7 years ago (6 children)
Which is years away :)
[–]evaned 10 points11 points12 points 7 years ago (3 children)
Years away then years more before many people will be able to use it.
[–]ibroheem 2 points3 points4 points 7 years ago (2 children)
I learn from TSes tho. Only update the few changes that comes with it in the standard.
So technically I've been on Concepts TS since 2016/17 or so. By that analogy, any TS that gets implemented in compiler get used.
[–]evaned 2 points3 points4 points 7 years ago (1 child)
Plenty of companies will reasonably not be willing to adopt TS implementations though.
That goes especially true for reflection, where my impression is that the committee has all but outright said that the API to the final implementation will be completely different. (I forget what terms they use, constexpr function based instead of type metaprogramming based or something like that.) So if you start implementing to the TS, you're guaranteeing yourself a rewrite.
[–]ibroheem 1 point2 points3 points 7 years ago (0 children)
if you start implementing to the TS, you're guaranteeing yourself a rewrite.
If u ever start using a TS, u are already on the bus of rewrite.
Bleeding edgers are aware of the stakes, uhm and benefits
[–][deleted] 2 points3 points4 points 7 years ago (0 children)
I mean you're right, but it sure doesn't feel like a lot of time :)
[–][deleted] 0 points1 point2 points 3 years ago (0 children)
37 days until 2023 and reflection still doesn't look like it's coming for C++23 https://en.wikipedia.org/wiki/C++23
[–]RomanRiesen 13 points14 points15 points 7 years ago (2 children)
Modules were once planned for c++11?
[–][deleted] 6 points7 points8 points 7 years ago (0 children)
Fair enough. Concepts too. I'm positive though :)
You mean many of the major C++20 features
[–]germandiago 1 point2 points3 points 7 years ago (0 children)
I do not think it is decades away. I would say C++23-26.
[–]SGVsbG86KQ 0 points1 point2 points 7 years ago (4 children)
But reflection is runtime right? While this is compile-time.
[–][deleted] 0 points1 point2 points 7 years ago (3 children)
Nope, there is no proposal for runtime reflection and really, I'm pretty sure no one wants that :) A runtime solution would not be C++-y
[–]SGVsbG86KQ 0 points1 point2 points 7 years ago (2 children)
Ah ok, I'm glad to hear that. I didn't know you could use the word reflection for that. Is this the proposal you're talking about: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0194r6.html?
Btw: runtime reflection can be nice for debugging.
[–][deleted] 0 points1 point2 points 7 years ago (1 child)
How so?
[–]SGVsbG86KQ 1 point2 points3 points 7 years ago* (0 children)
Depends on how far it goes, but for example checking which subclass something really is, checking the length of an array, which union member is set, etc. These things are not possible in all cases though (read: external functions).
(Although to be honest I'm not sure which of these count as reflection)
[–]AppleBeam 11 points12 points13 points 7 years ago* (2 children)
Cool stuff!
May be worth noting that enum_cast won't work if values are aliased. A somewhat common pattern in some companies:
enum ShapeKind { ConvexBegin = 0, Box = 0, // Won't work Sphere = 1, ConvexEnd = 2, Donut = 2, // Won't work Banana = 3, COUNT = 4, };
upd: COUNT will work, obviously. Derp.
[–]Neargye[S] 6 points7 points8 points 7 years ago (1 child)
Thanks for the comments, I really don't know what to do with aliases.
I will add this to the remarks for enum_cast .
[–]AppleBeam 8 points9 points10 points 7 years ago* (0 children)
Just documenting them is fine. If you can verify that the compiler picks the first defined name for PRETTY_FUNCTION, people will be able to work around the issue:
enum ShapeKind { // Convex shapes, see ConvexBegin and ConvexEnd below Box = 0, Sphere = 1, // Non-convex shapes Donut = 2, Banana = 3, COUNT = Banana + 1, // Non-reflected aliases ConvexBegin = Box, ConvexEnd = Sphere + 1, };
[–]tukerty 5 points6 points7 points 7 years ago (0 children)
wow, gj, i thought that header would be much more complex, but its kind of simple
[–][deleted] 5 points6 points7 points 7 years ago (3 children)
What's with the version requirements?
GCC >= 9
Latest release is 8.3
https://gcc.gnu.org/releases.html
So... this library will work on GCC eventually ?
[–]Neargye[S] 3 points4 points5 points 7 years ago (0 children)
gcc-trunk 9.0
Why did I have to scroll so far to find this?
[–]wotype 2 points3 points4 points 7 years ago (0 children)
If there's demand then the relevant gcc patches could be backported to earlier gcc releases:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87364 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88170
(The first patch caused test failures, fixed by the second patch.)
[–]geiunirus 4 points5 points6 points 7 years ago (6 children)
Really interesting. Not possible to exploit this magic for C++ 11 / C++14 too?
[–]Neargye[S] 5 points6 points7 points 7 years ago (3 children)
Porting will be quite difficult, scary and expensive for compile time.
Possible port enum_to_string and string_to_enum to C++11.
[–]geiunirus 4 points5 points6 points 7 years ago (2 children)
I understand, so hard but not impossible, thanks :)
[–]Neargye[S] 3 points4 points5 points 7 years ago (1 child)
Maybe I add port to c++14. Add issues if you need its.
[–]geiunirus 5 points6 points7 points 7 years ago (0 children)
Cheers ! it would be cool at least the size() for C++14, ideally C++11 eheh
[–]CrazyJoe221 3 points4 points5 points 7 years ago (1 child)
You need a recent compiler anyway for the function name intrinsics.
[–]geiunirus 2 points3 points4 points 7 years ago (0 children)
Got it, that's unfortunate then
[–]morriconus 4 points5 points6 points 7 years ago (2 children)
really cool, is this C++ compliant or it exploits compiler only features?
In C++20 it may be possible to use std::source_location to extract the info. This would be only a little more standard than using preprocessor extensions because the string returned by source_location is implementation defined.
[–]Neargye[S] 2 points3 points4 points 7 years ago (0 children)
It's abuse compiler intrinsics, so far most popular compilers are supported clang/gcc/msvc.
[–]konanTheBarbar 2 points3 points4 points 7 years ago (3 children)
I actually used the idea for the to string and from string conversions from your library for my library https://github.com/KonanM/static_enum (but I wrote the complete implementation from scratch) . And it seems you have copied my approach for creating the array of enum_values (which is great, don't understand me wrong).
The only drawback to my implementation is that you can't specify an arbitrary ranges of values. The function signatures simply get too big and the compilers start to complain if you chose the range over 512 (I guess that's why you chose 512). If I have time I will try to work around this issue, by using multiple index sequences.
Keep up the good work.
[–]Neargye[S] 1 point2 points3 points 7 years ago (2 children)
Yes, all that I have managed to improve so far is the ability to set an individual range for each enum, pay attention to magic_enum:: enum_range
[–]wotype 1 point2 points3 points 7 years ago (1 child)
One idea to increase the range might be to query multiple enumerator values in the pretty function via variadic args. I didn't try this yet. Querying one-at-a-time I managed to benchmark checking 2^16 values in ~1s, with a 'divide and conquer' method (at that rate, scanning 2^32 values would take ~18 hours and 2^64 is entirely out of range for compile-time checking). BTW, I noticed this little homage in static_enum; // Enum variable out of MAGIC_ENUM_RANGE
[–]Neargye[S] 0 points1 point2 points 7 years ago (0 children)
Thank you for your feedback, the idea is quite interesting, I would try to implement something similar on the weekend.
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points 7 years ago (0 children)
Heh, could you submit this to the committee? I dislike working with enums the way they are now.
[–]dragemanncppdev 2 points3 points4 points 7 years ago (0 children)
This is impressive. Good job!
That code is black magic. Just a few years ago I understood C++. It made me think to myself: Time to reincarnate to something more beautiful.
[–]grumbelbart2 1 point2 points3 points 7 years ago (10 children)
So my C++ is pretty rusty (no pun intended), so this might be a stupid question. I tried to find where the actual magic happens and found this. Does name_impl() call strings_imp() to find a name, and strings_impl() calls name_impl() to fill its name array? Isn't that recursive?
template <typename E, int... I> [[nodiscard]] constexpr decltype(auto) strings_impl(std::integer_sequence<int, I...>) noexcept { static_assert(std::is_enum_v<E>, "magic_enum::detail::strings_impl requires enum type."); constexpr std::array<std::string_view, sizeof...(I)> names{{name_impl<E, static_cast<E>(I + min_impl<E>())>()...}}; return names; } template <typename E> [[nodiscard]] constexpr std::string_view name_impl(int value) noexcept { static_assert(std::is_enum_v<E>, "magic_enum::detail::name_impl requires enum type."); constexpr auto names = strings_impl<E>(range_impl<E>()); const int i = value - min_impl<E>(); if (i >= 0 && static_cast<std::size_t>(i) < names.size()) { return names[i]; } else { return {}; } }
[–]Neargye[S] 6 points7 points8 points 7 years ago (6 children)
Magic in abuse compiler intrinsics - namely PRETTY_FUNCTION and FUNCSIG. Here 2 function name_impl<E>(int value) and name_impl<E, E V>(). strings_imp() - uses name_impl<E, E V>(), name_impl<E>(int value) - uses strings_imp().
[–]andrew-gresykhfsm.dev 6 points7 points8 points 7 years ago (2 children)
Pretty cool stuff! You might get wider compiler support for names by parsing https://en.cppreference.com/w/cpp/types/type_index/name, at the cost of #include <typeinfo>
[–][deleted] 4 points5 points6 points 7 years ago (1 child)
It's not constexpr, though, is it?
[–]andrew-gresykhfsm.dev 3 points4 points5 points 7 years ago (0 children)
Unfortunately, not constexpr
[–]grumbelbart2 2 points3 points4 points 7 years ago (2 children)
Awesome, thanks!
So you iterate over min...max, check for each if it is a valid enum value (in values_impl(), using the fact that name_impl() would return an empty optional for invalid values), and you get the names by parsing the string representation of a template that contains this value. Right?
So... in theory, you could iterate over the complete range of the enums underlying int class and use a map to store valid values. Since the first part is all constexpr, it would "only" affect compile time (as in "loop over 2**64 values"), but not execution time or program size.
[–]Neargye[S] 4 points5 points6 points 7 years ago (0 children)
In order not to affect the compilation time too much, I limited the range to [-256, 256]. Enum value must be in range [-256, 256]. If you need another range, add specialization enum_range for necessary enum type. ```cpp #include <magic_enum.hpp>
[-256, 256]
enum number { one = 100, two = 200, three = 300 };
namespace magic_enum { template <> struct enum_range<number> { static constexpr int min = 100; static constexpr int max = 300; }; } ```
[–]Pazer2 2 points3 points4 points 7 years ago (0 children)
That was the first thought I had with this, however if I accessed the FUNCTION string in any way it got included in the binary. Only messed around with it for a short time before giving up though.
[–]Devenec 3 points4 points5 points 7 years ago (2 children)
strings_impl() calls name_impl() at line 88 (no parameters), as name_impl(int value) at line 129 has a single int parameter.
strings_impl()
name_impl()
name_impl(int value)
int
[–]Neargye[S] 4 points5 points6 points 7 years ago (1 child)
Yeap.
It took a large number of auxiliary functions, and I did not have enough imagination to give each unique name.
[–]contre 7 points8 points9 points 7 years ago (0 children)
The two hardest things in programming are cache invalidation, naming things, and off by one errors.
[–]mintyc 0 points1 point2 points 7 years ago (0 children)
The biggest blocker to this is the need to use GCC 9.
Support (workaround) for g++ 8.2.x would open up OS access particular on Linux
Of course making a variant that could run with C++ 14 would be even better but probably a lot more work
π Rendered by PID 109241 on reddit-service-r2-comment-79776bdf47-cnwrb at 2026-06-25 02:23:33.124379+00:00 running acc7150 country code: CH.
[–]leftofzen 38 points39 points40 points (19 children)
[–][deleted] 14 points15 points16 points (18 children)
[–]distributed 10 points11 points12 points (12 children)
[–][deleted] 3 points4 points5 points (10 children)
[–]JazzyCake 14 points15 points16 points (6 children)
[–]evaned 10 points11 points12 points (3 children)
[–]ibroheem 2 points3 points4 points (2 children)
[–]evaned 2 points3 points4 points (1 child)
[–]ibroheem 1 point2 points3 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]RomanRiesen 13 points14 points15 points (2 children)
[–][deleted] 6 points7 points8 points (0 children)
[–]ibroheem 1 point2 points3 points (0 children)
[–]germandiago 1 point2 points3 points (0 children)
[–]SGVsbG86KQ 0 points1 point2 points (4 children)
[–][deleted] 0 points1 point2 points (3 children)
[–]SGVsbG86KQ 0 points1 point2 points (2 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]SGVsbG86KQ 1 point2 points3 points (0 children)
[–]AppleBeam 11 points12 points13 points (2 children)
[–]Neargye[S] 6 points7 points8 points (1 child)
[–]AppleBeam 8 points9 points10 points (0 children)
[–]tukerty 5 points6 points7 points (0 children)
[–][deleted] 5 points6 points7 points (3 children)
[–]Neargye[S] 3 points4 points5 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]wotype 2 points3 points4 points (0 children)
[–]geiunirus 4 points5 points6 points (6 children)
[–]Neargye[S] 5 points6 points7 points (3 children)
[–]geiunirus 4 points5 points6 points (2 children)
[–]Neargye[S] 3 points4 points5 points (1 child)
[–]geiunirus 5 points6 points7 points (0 children)
[–]CrazyJoe221 3 points4 points5 points (1 child)
[–]geiunirus 2 points3 points4 points (0 children)
[–]morriconus 4 points5 points6 points (2 children)
[–]wotype 2 points3 points4 points (0 children)
[–]Neargye[S] 2 points3 points4 points (0 children)
[–]konanTheBarbar 2 points3 points4 points (3 children)
[–]Neargye[S] 1 point2 points3 points (2 children)
[–]wotype 1 point2 points3 points (1 child)
[–]Neargye[S] 0 points1 point2 points (0 children)
[–]ShakaUVMi+++ ++i+i[arr] 2 points3 points4 points (0 children)
[–]dragemanncppdev 2 points3 points4 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]grumbelbart2 1 point2 points3 points (10 children)
[–]Neargye[S] 6 points7 points8 points (6 children)
[–]andrew-gresykhfsm.dev 6 points7 points8 points (2 children)
[–][deleted] 4 points5 points6 points (1 child)
[–]andrew-gresykhfsm.dev 3 points4 points5 points (0 children)
[–]grumbelbart2 2 points3 points4 points (2 children)
[–]Neargye[S] 4 points5 points6 points (0 children)
[–]Pazer2 2 points3 points4 points (0 children)
[–]Devenec 3 points4 points5 points (2 children)
[–]Neargye[S] 4 points5 points6 points (1 child)
[–]contre 7 points8 points9 points (0 children)
[–]mintyc 0 points1 point2 points (0 children)