4 ms·
I was nodding in agreement throughout the article until the solution was presented, or at least the implementation of it. Maybe it's truly genius and am I just
by stinos 12y ago
I was nodding in agreement throughout the article until the solution was presented, or at least the implementation of it. Maybe it's truly genius and am I just not understanding it properly, but the fact I had to go over it multiple times to grasp wtf is going one isn't exactly a good sign, I think.
The idea behind the solution is definitely ok: you define a type with a bunch of immutable properties describing it. But surely there must be more elegant/easier to read/easier to understand ways to do this than to have a bunch of macros/includes inside enums and whatnot? Moreover the TUPLE macro is declared twice with the same arguments (and then the arguments are repeated once more) so that means extending the type has to be done in 2 places which is exactly one of the things warned about earlier.
- JoeAltmaier 12y ago2 places is better than N places. At the cost of slightly heavier enum declarations (2 places), you get rid of tests throughout the code for particular enum values. Also consider inheiritance and enums. Derived classes have to jump through hoops to extend enum space e.g. enum { tractor = truck+1, crane, bulldozer}; where truck was the last enum value in the base class. With the tuple method, you just add some more tuples.
- stinos 12y agoYes of course inheritance (if you can even call it that) is problematic and indeed one, if not the whole, point of the solution is having to add an antry means having to do it in one place only, but my question remains: does it have to be with a macro? I threw something together and this seems sort of equivalent but (imo) with less of the uglyness? enum class VehicleType { Car, Bicycle }; using tuple = std::tuple< std::string, int, int >; using map = std::map< VehicleType, tuple >; const map VehicleTypes = { { VehicleType::Car, tuple( "car", 4, 10 ) }, { VehicleType::Bicycle, tuple( "bicycle", 3, 20 ) } }; const tuple& get_it( VehicleType type ) { static tuple def( "unknown", -1, -1 ); auto it = VehicleTypes.find( type ); return it == VehicleTypes.end() ? def : it->second; } std::string getVehicleTypeName( VehicleType type ) { return std::get< 0 >( get_it( type ) ); }
- Someone1234 12y agoThis is exactly why I am really happy to be working in a language which doesn't support macros. Are they performant? Yes. But they absolutely ruin code readability and make debugging harder also (as you're stepping through "code" which only exists post-compile). I felt like the OP made a great point about enums and I agree.
- EpicEng 12y agoThey do have downsides, but you gloss over the main reason to use macros; they're an extremely powerful tool.
- Someone1234 12y agoMeh. People are expensive, compute is cheap. If code is twice as hard to debug, you better have a darn cost saving reason to be working in inefficient language like C/C++.
- EpicEng 12y agoWell, that's not always true (thinking of the numerous times I have had to optimize code written by people with this attitude), but I wasn't speaking about performance. Macros allow you to do things in e.g. C which cannot be done via any other mechanism in the language.
- copsarebastards 12y ago> Macros allow you to do things in e.g. C which cannot be done via any other mechanism in the language. This isn't really an argument in favor of macros so much as an argument against minimally-featured languages like C. To be clear, I'm not against using macros in every case. I think a lot of the danger of macros in C comes from C's syntax: macros become a much more powerful tool when you're using a homoiconic language like Lisp. There are a few different projects which have attempted to write languages with C-like semantics and Lisp-like syntax, but sadly none have gained traction.
- 12y ago