4 ms·
> Calculating the size of a static array. #include <type_traits> int myarray[] = { 4, 5, 6, 7, 8, 9 }; int x = std::extent<decltype(foo)>::value; // ret
by colanderman 9y ago
> Calculating the size of a static array.
#include <type_traits>
int myarray[] = { 4, 5, 6, 7, 8, 9 };
int x = std::extent<decltype(foo)>::value; // returns 6
> Converting a string to an enum
Generally a bad idea, as it couples a protocol (whatever is feeding you the strings) to symbols in your language. Often, one of those has constraints that the other cannot meet.
> Binary file includes
objcopy -I binary -O elf64-x86-64 -B i386:x86-64:intel in.bin out.o
Not the prettiest, but, why should a language do the linker's job?
> FourCC codes
How often does this come up, that you can't write a 10-line class to do what you want? Not to mention the obvious issue of endianness in the example given. Last time I had to do this I was writing a PNG parser, which was not something I should have been doing.
> Types as first-class primitives
I've been coding for 25 years and never needed nor wanted this. I know not everyone agrees, but personally I find reliance on RTTI to be a code smell. (Granted, pre-C++17 it's kind of forced due to lack of a proper variant type.)
(I realize the above is opinionated, but… so is the OP! :)
- bstamour 9y agoOr use the std::size free function. It's overloaded to work with C-style arrays.
- colanderman 9y agoDid not know about that, though unfortunately it's C++17 only.
- bstamour 9y agoUnfortunately yes. The implementation is straight forward though: template <typename Container> std::size_t size(Container const& c) { return c.size(); } template <typename T, std::size_t K> std::size_t size(T (&)[K]) { return K; }
- stabbles 9y agoOP complains about C-style arrays when criticizing C++. Just using `std::array` makes life easier.
- colanderman 9y agoAgreed, though unfortunately pre-C++17 you must specify the size when defining the array.
- sseagull 9y agoYeah that one is a little weird. C++11 included std::array to solve that problem (among others), but he doesn't use it and then complains about it anyway.
- jcelerier 9y ago> Generally a bad idea, as it couples a protocol (whatever is feeding you the strings) to symbols in your language. Is it intrinsincally bad though ? For instance F# is able to couple actual data files like CSV to symbols and types in the language, and this allows for very efficient development: http://fsharp.github.io/FSharp.Data/library/CsvProvider.html http://fsharp.github.io/FSharp.Data/library/CsvProvider.html > I know not everyone agrees, but personally I find reliance on RTTI to be a code smell. Again, why ? There are plenty of cases where this has proven quite useful. Besides, "types as first-class primitives" does not necessarily imply "run-time": in the C++ spirit it would most certainly be a compile-time only feature.
- colanderman 9y ago> For instance F# is able to couple actual data files like CSV to symbols and types in the language Of course that breaks once your CSV header names don't match allowable symbol names. Notice the example linked doesn't show accessing the "Adj Close" field. (Presumably there is a way to get at this in F#? There's no way to "escape" characters in symbols in C++ though.) Sure, it speeds development, but first time a requirement comes down that says "foo_bar field must be named foo-bar", what should be a one-character change suddenly becomes something much more. > why ? There are plenty of cases where this has proven quite useful. "Useful" and "bad idea" are not mutually exclusive. A lot of things which are "useful" – i.e., which speed development or save keystrokes – have costs which hamper maintenance. (Think macros.) RTTI generally implies that your program has logic to do something based on the type of a value, rather than on the meaning of a value. Say I have an object, BasketOfApples, with a field size_of_basket, which can be either an integer or a string. If it's an integer, it refers to the number of apples the basket can hold. If it's a string, it's either "small", "medium", or "large". OK so far. But now I want my BasketOfApples to also be able to have a size defined as the weight in pounds it can hold. I can't use an integer again, that already has meaning! But I want a numeric type. So I'm forced to either choose a distinct numeric type (say float), or use an enum to distinguish the cases. The former forces me to make a suboptimal design decision. The latter is probably what I should have done in the first place. So now my BasketOfApples has an enum field, type_of_basket_size, which determines the meaning of the basket_size value. Not only does type_of_basket_size do what RTTI failed to, it obviates the need for it, and is likely a bit more efficient to boot. (BTW, you see this all the time with C++ constructors. You can't have two constructors which mean different things but accept the same types without using a dummy "tag" argument.) Languages with tagged variant types (e.g. OCaml, and I presume by extension, F#) don't have this problem and don't need (or even supply) RTTI information, and they get along just fine. To me, using a feature that isn't available or missed in other "serious" languages, which incompletely accomplishes the task to which it's set, is a code smell. BTW, I recognize that not everyone agrees with me on this point. But I've been coding like RTTI doesn't exist for decades in various languages and not once have I missed it. > Besides, "types as first-class primitives" does not necessarily imply "run-time": in the C++ spirit it would most certainly be a compile-time only feature. The OP's example (copying an object without knowing its type at compile time) specifically requires RTTI.
- tlb 9y ago> objcopy -I binary -O elf64-x86-64 -B i386:x86-64:intel in.bin out.o Neat! In the past I've used perl scripts to munge into C source. FYI, it generates symbols named after the filename: tlb@london:~/ur$ objcopy -I binary -O elf64-x86-64 -B i386:x86-64:intel /etc/services services.o tlb@london:~/ur$ objdump -t services.o SYMBOL TABLE: 0000000000000000 l d .data 0000000000000000 .data 0000000000000000 g .data 0000000000000000 _binary__etc_services_start 0000000000004c95 g .data 0000000000000000 _binary__etc_services_end 0000000000004c95 g *ABS* 0000000000000000 _binary__etc_services_size And in C++ you can get the contents with: extern const char _binary__etc_services_start; extern const char _binary__etc_services_end; string services(&_binary__etc_services_start, &_binary__etc_services_end);
- mark-r 9y ago> Not the prettiest, but, why should a language do the linker's job? Because it's not cross platform. I have no idea how to do the equivalent in Visual Studio.
- colanderman 9y agoPoint taken, though I would think MinGW's objcopy should be able to do something similar. (Obviously not part of Visual Studio.)
- to3m 9y agoStrictly speaking I think the term for what's requested would be reflection - but I don't think these terms are especially precise ones. The sorts of things I've used reflection for: - logging - getting the name of things' types, turning enums into strings, etc. - generating debugging UI - for every bool field in your object, you get a check box; for every enum field, a combo box; for every string field, a text box; and so on - serialization/deserialization - it has limitations, but you can get surprisingly far before you run into them, and for many situations it doesn't matter - scripting language integration - for every type of interest in your program, find its fields and methods, and link those up to the scripting system - dependency injection - given a set of known services, when creating an object (perhaps by name, provided at runtime, which you match to a type by scanning the list of types available) provide it with the services it needs (determined by, say, examining the types of the parameters of its constructor). Typically you'd cross-reference types of parameter with types of each service to match them up, but there are various options Especially good with a C#-like metadata system that lets you assign user-defined properties to fields that your calling code can query to get further info. For example, you might not want to serialize certain fields, or you might want to hide some fields from the UI, and so on. (If this doesn't convince you, fine; for my money, though, this is the #1 missing feature from C++. But, like the post's author, my background is working on video games... maybe this is just stuff that only video games people would want?)
- colanderman 9y agoenum→string I agree 100% is useful for debugging. string→enum, and enum→string for production purposes I find questionable, since they couple your implementation internals to an externally-visible protocol, of which a change in one should not necessitate a change in the other. Of course relying on an implicit mapping speeds initial development… but I'm the one who has to maintain those things ;)