1

In C++11 and later, the <type_traits> header contains many classes for type checking, such as std::is_empty, std::is_polymorphic, std::is_trivially_constructible and many others.

While we use these classes just like normal classes, I cannot figure out any way to possibly write the definition of these classes. No amount of SFINAE (even with C++14/17 rules) or other method seems to be able to tell if a class is polymorphic, empty, or satisfy other properties. An class that is empty still occupies a positive amount of space as the class must have a unique address.

How then, might compilers define such classes in C++? Or perhaps it is necessary for the compiler to be intrinsically aware of these class names and parse them specially?

Bernard
  • 5,209
  • 1
  • 34
  • 64
  • 1
    http://libcxx.llvm.org/type_traits_design.html – cpplearner Jul 08 '17 at 08:44
  • I know I've read this on SO sometime before, just can't remember where. – Passer By Jul 08 '17 at 08:44
  • Here's one https://stackoverflow.com/questions/35531309/how-is-stdis-emptyt-implemented-in-vs2015-or-any-compiler – Passer By Jul 08 '17 at 08:45
  • @PasserBy Do you mean [this one](https://stackoverflow.com/questions/36374178/why-is-there-no-language-support-in-c-for-all-c-standard-library-type-traits)? – Rakete1111 Jul 08 '17 at 08:46
  • @Rakete1111 Not that one, I've seen one that I love the most, included in which is a complete list of traits (most likely) impossible to write without compiler support – Passer By Jul 08 '17 at 08:47
  • 5
    @PasserBy Ah, so https://stackoverflow.com/questions/20181702/which-type-traits-cannot-be-implemented-without-compiler-hooks – Rakete1111 Jul 08 '17 at 08:48
  • Some traits requires special compiler support. Nothing in the standard specifies that the standard library must be implement with only core language features. Since 98, `std::less` always defined a total order for any pointer type, while direct comparison with `<` did not. This is another example where an exception is made. – StoryTeller - Unslander Monica Jul 08 '17 at 08:51
  • g++ 5.1.0 by using intrinsic(s) ie cheating :) eg `is_polymorphic` uses `__is_polymorphic` which is a built-in. – Richard Critten Jul 08 '17 at 08:51
  • @StoryTeller Can't that be done by casting to `intptr_t`? (Which, alright, the `typedef` didn't exist back in the day, but there was always a wide enough integer type to use.) – BoBTFish Jul 08 '17 at 09:01
  • @BoBTFish - Pointer to integer conversions were always (a) implementation defined and (b) made no guarantees that the mapping preserve order even inside the same array. – StoryTeller - Unslander Monica Jul 08 '17 at 09:02
  • @StoryTeller Ah, ok. The first part wouldn't matter much, you could still implement using the language rather than compiler magic, but I hadn't realised the second part. I'd be very surprised by any implementation that didn't! – BoBTFish Jul 08 '17 at 09:12
  • @BoBTFish - So would I. But some crazy compilers do optimize on such things. – StoryTeller - Unslander Monica Jul 08 '17 at 09:13
  • @StoryTeller doesn't the standard explicitly state that a pointer can be `reinterpret_cast`ed to an instance of type `uintptr_t` and still hold it's value? – Curious Jul 08 '17 at 09:34
  • @StoryTeller or am i missing something here :( – Curious Jul 08 '17 at 09:46
  • @Curious - The standard says you can cast a pointer to an integer, then back, and get the same address. There is nothing there about preserving order *as integers*. – StoryTeller - Unslander Monica Jul 08 '17 at 11:29

1 Answers1

2

Back in the olden days, when people were first fooling around with type traits, they wrote some really nasty template code in attempts to write portable code to detect certain properties. My take on this was that you had to put a drip-pan under your computer to catch the molten metal as the compiler overheated trying to compile this stuff. Steve Adamczyk, of Edison Design Group (provider of industrial-strength compiler frontends), had a more constructive take on the problem: instead of writing all this template code that takes enormous amounts of compiler time and often breaks them, ask me to provide a helper function.

When type traits were first formally introduced (in TR1, 2006), there were several traits that nobody knew how to implement portably. Since TR1 was supposed to be exclusively library additions, these couldn't count on compiler help, so their specifications allowed them to get an answer that was occasionally wrong, but they could be implemented in portable code.

Nowadays, those allowances have been removed; the library has to get the right answer. The compiler help for doing this isn't special knowledge of particular templates; it's a function call that tells you whether a particular class has a particular property. The compiler can recognize the name of the function, and provide an appropriate answer. This provides a lower-level toolkit that the traits templates can use, individually or in combination, to decide whether the class has the trait in question.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165