138

According to cppreference.com size_t is defined in several headers, namely

<cstddef>
<cstdio>
<cstring>
<ctime>

And, since C++11, also in

<cstdlib>
<cwchar> 

First of all, I wonder why this is the case. Isn't this in contradiction to the DRY principle?

Which one of the above headers should I include to use size_t? Does it matter at all?

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 3
    Open corresponding header files and find the definition. – i486 Apr 13 '16 at 09:52
  • 45
    @i486 - That's a great way to write brittle non-portable code! – Sean Apr 13 '16 at 09:53
  • @i486 Dont really understand, I quite trust that it is defined in those headers – 463035818_is_not_an_ai Apr 13 '16 at 09:53
  • All of these headers are *C* headers. They are needed if you call C functions instead of their C++ equivalents. You probably shouldn't be using them and find the C++ equivalents – Panagiotis Kanavos Apr 13 '16 at 09:55
  • 4
    @PanagiotisKanavos C headers that are part of the C++ standard library and probably aren't duplicated in any of your alleged 'true C++' headers. What was your point, exactly? – underscore_d Apr 13 '16 at 09:57
  • 15
    I always used `` for `std::size_t` – Boiethios Apr 13 '16 at 09:58
  • @Morovaille Yeah, I'm (informally) pretty sure that's the 'go to' place for this, even if it ends up being included in the others. – underscore_d Apr 13 '16 at 09:58
  • @underscore_d didn't mention any "true" headers but using C functions when there are C++ equivalents does cause problem. For example, mixing the string headers – Panagiotis Kanavos Apr 13 '16 at 10:01
  • 1
    @sean Asking in SO for everything is not better way to write portable code. – i486 Apr 13 '16 at 10:02
  • 1
    @i486 - I know, I was being sarcastic! – Sean Apr 13 '16 at 10:04
  • 5
    @PanagiotisKanavos Sure, generally that's good advice, but in this case it doesn't seem relevant - as there is no C++ replacement for `std::size_t`, and the OP wasn't advocating using legacy C functions, just observing the quote about them sharing the typedef. I doubt anyone reading this thread would be misled into using legacy types/functions because of this, but if you want to be sure they don't, then fair enough! – underscore_d Apr 13 '16 at 10:05
  • Possible duplicate of [What's the difference between size\_t and int in C++?](http://stackoverflow.com/questions/502856/whats-the-difference-between-size-t-and-int-in-c) – Jim Fell Apr 04 '17 at 12:42
  • @JimFell not really clear to my why you think it is a dupe. I know what is the diff between `int` and `size_t` (and I already knew it when asking this question). The accepted answers there also mentions just two more headers that define it, but does not say which of those one should use – 463035818_is_not_an_ai Apr 04 '17 at 13:21
  • 1
    @JimFell actually the accepted answer on that question only mentions the c headers, but of course I would prefer the c++ headers – 463035818_is_not_an_ai Apr 04 '17 at 13:22
  • excellent question. I was also intrigued by this some time back. +1 for this – AnotherDeveloper Jun 28 '19 at 04:00

4 Answers4

131

Assuming I wanted to minimize the functions and types I was importing I'd go with cstddef as it doesn't declare any functions and only declares 6 types. The others focus on particular domains (strings, time, IO) that may not matter to you.

Note that cstddef only guarantees to define std::size_t, that is, defining size_t in namespace std, although it may provide this name also in the global namespace (effectively, plain size_t).

In contrast, stddef.h (which is also a header available in C) guarantees to define size_t in the global namespace, and may also provide std::size_t.

Sean
  • 60,939
  • 11
  • 97
  • 136
  • 4
    Is there any guarantee that `size_t` from `cstddef` is the same and will always be the same as the others? Seems like there should be a common header file with common definitions like `size_t`... – SnakeDoc Apr 13 '16 at 20:52
  • 1
    @SnakeDoc and as if by magic, another answer here has already observed exactly that happening, via an 'internal' header. – underscore_d Apr 13 '16 at 21:00
  • 5
    @SnakeDoc Yes, and that header is `cstddef`. – user253751 Apr 14 '16 at 01:26
  • @immibis the question then is why do other header files define their own...? – SnakeDoc Apr 14 '16 at 14:39
  • 3
    @SnakeDoc, who says they define their own? All the standard says is it will be defined after including those headers, it doesn't say they all have to redefine it. They could all include ``, or they could all include some internal header that just defines `size_t`. – Jonathan Wakely Apr 15 '16 at 12:27
  • @SnakeDoc, and of course there's a guarantee that `size_t` in `` is the same as in the other headers, what kind of idiots do you take the library designers for? It's defined in ``, but may also be available (directly or indirectly) by including other headers. – Jonathan Wakely Apr 15 '16 at 12:44
  • @JonathanWakely The OP stated *According to cppreference.com size_t is defined in several headers*... and frankly, being a library designer doesn't imply not being an idiot. And no way you can claim "of course" here, since multiple definitions may very well have legitimate purposes and/or be completely intentional (minimize dependencies of a particular header file). So unless you can point to something that explicitly prevents multiple incompatible definitions, then you statements are a little too liberal. – SnakeDoc Apr 15 '16 at 14:47
  • @SnakeDoc, does the C++ standard say you can't include all those headers at once? No. So it must be possible, and therefore the definitions must be compatible. Any other conclusion is inconsistent. Also, _"multiple definitions may very well have legitimate purposes and/or be completely intentional (minimize dependencies of a particular header file)"_ Why would doing that imply **incompatible** definitions? So I repeat, of course the definitions are the same (which does not imply there is only one definition, just that all definitions are equivalent). – Jonathan Wakely Apr 15 '16 at 15:02
  • If you're using "the same" to mean "come from the same file" then that's irrelevant, and you don't need to know or care. Maybe they do, maybe they don't. All that matters is that the definitions are equivalent (i.e. refer to the same type) and that is obviously true because any other conclusion would mean you can't include different standard headers without getting compiler errors. – Jonathan Wakely Apr 15 '16 at 15:08
  • @JonathanWakely The entire point of this question was the ambiguity around this subject. You're making an assumption that things will always be the same, but there's multiple implementations of the standard and there literally is nothing enforcing these definitions to be the same, so you cannot use "of course" here. Your aggressiveness here is plain ridiculous. Go have a bad day somewhere else please. – SnakeDoc Apr 15 '16 at 15:14
  • @SnakeDoc, you don't get different headers from separate implementations, so your concern is unfounded. There is no way that you can get inconsistent definitions of `size_t` from different headers unless you have deliberately or carelessly broken your compiler. Things will always be the same **for a given implementation**. The type of a `sizeof` expression doesn't just vary depending on the day of the week. If you still doubt that, take it from someone who actually implements the standard library for a living that it's true and you can rely on it being the same in each of those headers. – Jonathan Wakely Apr 15 '16 at 17:54
  • @JonathanWakely I asked a simple question, and have no idea why you're so hellbent on being hostile. You're not immune to being an idiot just because you hack on a library for money. You work on a specific implementation of a standard, which has no mechanism to enforce the design you talk about. The standard may change, and/or other implementations may choose to differ. It's moronic that one can import any type from multiple header files - there should be a single canonical import to get a specific type. ie. it's bad design to allow header imports to chain other imports into your program. – SnakeDoc Apr 15 '16 at 19:39
  • @JonathanWakely That's the core essence of my initial question. And yes, I understand that's just how C et al works, but it's dumb and causes exactly this confusion the OP came asking about. – SnakeDoc Apr 15 '16 at 19:41
  • So although `` defines functions like `strftime` which use `size_t` in their interface, and `` defines functions like `memcpy` that use `size_t` in their interface, it's moronic for `size_t` to be defined after including those headers? I don't think you've thought this through. – Jonathan Wakely Apr 15 '16 at 21:37
  • 2
    Is the `csttddef` in the answer a typo? Maybe `cstddef` is meant? – Erik Sjölund Dec 30 '17 at 12:50
54

In fact the synopsis (included in the C++ standard) of several headers specifially include size_t as well as further headers define the type size_t (based on the C standard as the <cX> headers are just ISO C <X.h> headers with noted changes where removal of size_t is not indicated).

The C++ standard however, refers to <cstddef> for the definition of std::size_t

  • in 18.2 Types,
  • in 5.3.3 Sizeof,
  • in 3.7.4.2 Deallocation functions (which refers to 18.2) and
  • in 3.7.4.1 Allocation functions (also refers to 18.2).

Therefore and because of the fact that <cstddef> only introduces types and no functions, I'd stick to this header to make std::size_t available.


Note a few things :

  1. The type of std::size_t is obtainable using decltype without including a header

    If you're planning to introduce a typedef in your code anyway (i.e. because you write a container and want to provide a size_type typedef) you can use the global sizeof, sizeof... or alignof operators to define your type without including any headers at all since theose operators return std::size_t per standard definition and you can use decltype on them:

    using size_type = decltype(alignof(char));
    
  2. std::size_t is not per se globally visible although functions with std::size_t arguments are.

    The implicitly declared global allocation and deallocation functions

    void* operator new(std::size_t);
    void* operator new[](std::size_t);
    void operator delete(void*);
    void operator delete[](void*);
    

    do NOT introduce size_t, std or std::size_t and

    referring to std or std::size_t is ill-formed unless the name has been declared by including the appropriate header.

  3. The user may not redefine std::size_t although it is possible to have multiple typedefs referring to the same type in the same namespace.

    Although, the occurrence of multiple definitions of size_t within std is perfectly valid as per 7.1.3 / 3, it is not allowed to add any declarations to namespace std as per 17.6.4.2.1 / 1:

    The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified.

    Adding a proper typedef for size_t to the namespace does not violate 7.1.3 but it does violate 17.6.4.2.1 and leads to undefined behaviour.

    Clarification: Try not to misinterpret 7.1.3 and do not add declarations or definitions to std (except a few template specialization cases where a typedef is not a template specialization). Extending the namespace std

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
  • 1
    You miss the fact that a duplicate typedef does not introduce a new type. It merely adds a duplicate typedef, which is perfectly valid. – Maxim Egorushkin Apr 13 '16 at 11:58
  • @MaximEgorushkin: I do not claim that adding a redefining typedef to `std` is invalid because duplicate typedefs are illegal. I state that it is illegal because you simply may not add definitions to `namespace std` - no matter whether they would be legal. – Pixelchemist Apr 13 '16 at 12:00
  • What could potentially break, given all we know from all these standard quotes? – Maxim Egorushkin Apr 13 '16 at 12:04
  • 12
    @MaximEgorushkin: Anything. That's what undefined behaviour is about, isn't it? The point that it *may* work or even the point that it *does* not break on any arbitrary compiler does not make the behaviour of the program defined according to the standard. Or as 'fredoverflow' put it nicely [here](http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior): "The C++ standard has the only vote, period." – Pixelchemist Apr 13 '16 at 12:14
  • I would like you to use your critical thinking. What could potentially break? – Maxim Egorushkin Apr 13 '16 at 12:19
  • @MaximEgorushkin The simplest breakage would be a compiler error enforcing the prohibition. But considering the habit of compiler writers to abuse any undefined behaviour I would avoid incurring that risk, whenever feasible. – CodesInChaos Apr 13 '16 at 12:57
  • @MaximEgorushkin: Your code could be using a subtly different definition than another library (say, the C++ standard library), but due to alignment, appear to keep working for 18 years, until a very specific value is passed in which case it triggers a branch, executes some random code, and deletes all the files in the user's documents directory. whoops. – Mooing Duck Apr 14 '16 at 20:27
  • @MooingDuck, if the standard says that `std::size_t` is the same type as `::size_t` which is the same type as the result of `sizeof(1)` then how could it be a subtly different definition? If it is, then the implementation is non-conforming. – Jonathan Wakely Apr 15 '16 at 12:29
  • @JonathanWakely: I overlooked the context of the question, you're right. – Mooing Duck Apr 15 '16 at 17:42
8

All standard library header files have the same definition; it does not matter which one you include in your own code. On my computer, I have the following declaration in _stddef.h. This file is included by every file you listed.

/*
   Define the size_t type in the std namespace if in C++ or globally if in C.
   If we're in C++, make the _SIZE_T macro expand to std::size_t
*/

#if !defined(_SIZE_T) && !defined(_SIZE_T_DEFINED)
#  define _SIZE_T_DEFINED
#if defined(_WIN64)
   typedef unsigned __int64 size_t;
#else
   typedef unsigned int size_t;
#endif
#  if defined(__cplusplus)
#    define _SIZE_T std::size_t
#  else
#    define _SIZE_T size_t
#  endif
#endif
VLL
  • 9,634
  • 1
  • 29
  • 54
  • 2
    not sure, but I think it does matter for compilation time, no? – 463035818_is_not_an_ai Apr 13 '16 at 09:57
  • @tobi303 not for this specific question. Yes, you may add a larger header than necessary, but then you *already* addedd a C header in a C++ project. Why do you need `size_t` in the first place? – Panagiotis Kanavos Apr 13 '16 at 10:00
  • It's not a good idea to use OS macro sniffing to define `size_t`. You can define it more portably as `using size_t = decltype( sizeof( 42 ) )`. But there's no need, since `` has almost zero cost. – Cheers and hth. - Alf Sep 29 '16 at 18:05
7

You could do without a header:

using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); //  The shortest is my favourite.
using size_t = decltype(sizeof "anything");

This is because the C++ standard requires:

The result of sizeof and sizeof... is a constant of type std::size_t. [ Note: std::size_t is defined in the standard header <cstddef> (18.2). — end note ]

In other words, the standard requires:

static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
              "This never fails.");

Also note, that it is perfectly fine to make this typedef declaration in the global and in std namespace, as long as it matches all other typedef declarations of the same typedef-name (a compiler error is issued on non-matching declarations).

This is because:

  • §7.1.3.1 A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.

  • §7.1.3.3 In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.


To sceptics saying that this constitutes an addition of a new type into namespace std, and such an act is explicitly prohibited by the standard, and this is UB and that is all there to it; I have to say that this attitude amounts to ignoring and denying deeper understanding of the underlying issues.

The standard bans adding new declarations and definitions into namespace std because by doing so the user may make a mess of the standard library and shoot his entire leg off. For the standard writers it was easier to let the user specialize a few specific things and ban doing anything else for good measure, rather than ban every single thing which the user should not do and risk missing something important (and that leg). They did it in the past when requiring that no standard container shall be instantiated with an incomplete type, while in fact some containers could well do (see The Standard Librarian: Containers of Incomplete Types by Matthew H. Austern):

... In the end, it all seemed too murky and too poorly understood; the standardization committee didn't think there was any choice except to say that STL containers aren't supposed to work with incomplete types. For good measure, we applied that prohibition to the rest of the standard library too.

... In retrospect, now that the technology is better understood, that decision still seems basically right. Yes, in some cases it's possible to implement some of the standard containers so that they can be instantiated with incomplete types — but it's also clear that in other cases it would be difficult or impossible. It was mostly chance that the first test we tried, using std::vector, happened to be one of the easy cases.

Given that the language rules require std::size_t to be exactly decltype(sizeof(int)), doing namespace std { using size_t = decltype(sizeof(int)); } is one of those things that do not break anything.

Prior to C++11 there was no decltype and thus no way to declare the type of sizeof result in one simple statement without getting a good deal of templates involved. size_t aliases different types on different target architectures, however, it would not be an elegant solution to add a new built-in type just for the result of sizeof, and there are no standard built-in typedefs. Hence, the most portable solution at the time was to put size_t type alias in some specific header and document that.

In C++11 there is now a way to write down that exact requirement of the standard as one simple declaration.

Community
  • 1
  • 1
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • that just introduces one more definition of `size_t` which I would like to avoid – 463035818_is_not_an_ai Apr 13 '16 at 09:50
  • 1
    @tobi303 Regardless, this definition is going to be as good as others coming from the standard headers. – Maxim Egorushkin Apr 13 '16 at 09:52
  • no its not, because its my own definition instead of the standard one – 463035818_is_not_an_ai Apr 13 '16 at 09:55
  • 1
    That's not even right. `size_t` is defined to be unsigned, and yet you've defined is as `signed`. The shows the problem with trying to cut and paste your way around using the standard headers! – Sean Apr 13 '16 at 09:55
  • 10
    @Sean What you wrote does not make any sense. – Maxim Egorushkin Apr 13 '16 at 09:56
  • 2
    @tobi303 This typedef is exactly the same as the global `::size_t` typedef. You can `typedef` the same type many times, as long as it is mapped to the same type. – Maxim Egorushkin Apr 13 '16 at 09:57
  • 2
    @underscore_d _defined_ and _advised_ are different things. – Maxim Egorushkin Apr 13 '16 at 09:58
  • 1
    @MaximEgorushkin exactly. By missing the difference between signed and unsigned this definition added an *incompatiblity*. An even worse one - `size_t` is system-defined. Why should it be `int` ? – Panagiotis Kanavos Apr 13 '16 at 09:58
  • 7
    @PanagiotisKanavos What are your talking about? This `size_t` is unsigned. – Maxim Egorushkin Apr 13 '16 at 09:59
  • 17
    @MaximEgorushkin Half of them did not understood this code... it works perfectly. However, I do not like this way : it is better, imo, to include a header and let the standard define it. – Boiethios Apr 13 '16 at 10:01
  • @MaximEgorushkin Well, _maybe_ (I've not tested this or compared it to any other bit of the Standard) in most real-life implementations you don't need to physically include the typedef, but it's probably best to do this, at least to avoid any esoteric problems later. – underscore_d Apr 13 '16 at 10:02
  • 3
    @Morovaille Yeah, the number of downvotes indicate how many people do not undertstand C++. – Maxim Egorushkin Apr 13 '16 at 10:02
  • 1
    You're right, my mistake! However, your answer feels like a really awkward (and hacky) way to avoid including a header! – Sean Apr 13 '16 at 10:03
  • 9
    Guys, at least learn the effing language before you go downvoting perfectly correct answers. – Frédéric Hamidi Apr 13 '16 at 10:04
  • 1
    Maybe not awkward but *clever*. Clever code needs some comments around it. – anatolyg Apr 13 '16 at 10:04
  • 11
    Tom said, "There are 6 standard library headers defining the same thing! That is insane! We need one and only one definition of `size_t`!" One minute later, Mary said, "OMG! There are 7 definitions of `size_t` across standard library headers and a project header Tom is editing! There are probably more in the 3rd party libraries!" https://xkcd.com/927/ –  Apr 13 '16 at 10:05
  • 5
    Explanation: Return type of `sizeof` is `size_t`. This code introduces a type, which is equal to the return type of `sizeof`, and names that `size_t`. – VLL Apr 13 '16 at 10:08
  • 2
    @NickyC: No, you cannot add a `std::size_t` definition anyway since adding to `std` isn't permitted. But depending on what you're up to (i.e. implementing some kind of Container defining a `size_type`) you may want to introduce a new typedef and then this answer is valid way to do so. – Pixelchemist Apr 13 '16 at 10:08
  • 3
    @anatolyg If I wanted to be clever I would do `using size_t = decltype(sizeof(1));`, lol. – Maxim Egorushkin Apr 13 '16 at 10:09
  • 3
    @Pixelchemist This would be a duplicate declaration, does not break ODR. – Maxim Egorushkin Apr 13 '16 at 10:10
  • Wow, how did this get to the positive side so quickly? ;) – underscore_d Apr 13 '16 at 10:12
  • 1
    @Pixelchemist Note that in my comment, there is no `std::`. It is perfectly fine to introduce things like `mylib::binary_tree::size_type`. I just feel questionable to define the 7th global `size_t` when there are 6 `std::size_t` available. –  Apr 13 '16 at 10:13
  • @MaximEgorushkin: The standard does not permit (with few exceptions) adding definitions to the namespace `std` and I think that typedefs are not allowed. It's not about ODR. – Pixelchemist Apr 13 '16 at 10:13
  • @NickyC: Where it is probably suboptimal to introduce global typedefs anyway. ;) – Pixelchemist Apr 13 '16 at 10:14
  • 1
    @Pixelchemist This does not add a new type into `std`, neither redefines any type, merely a duplicate declaration. This does not break ODR. Totally harmless. – Maxim Egorushkin Apr 13 '16 at 10:17
  • 1
    @MaximEgorushkin: `The behavior of a C++ program is undefined if it adds declarations or definitions to namespace `std`.` This includes duplicate declarations. – Pixelchemist Apr 13 '16 at 10:22
  • @Pixelchemist where did you see the namespace std ? – Boiethios Apr 13 '16 at 10:24
  • 1
    @Pixelchemist _This includes duplicate declarations._ - what sentence of the standard is this coming from? – Maxim Egorushkin Apr 13 '16 at 10:27
  • 1
    @Morovaille: I brought up that you can't declare `std::size_t` anyway and as such you do not add "another" `std::size_t` as @NickyC suggests but rather a `size_t` (hopefully) into your local environment. – Pixelchemist Apr 13 '16 at 10:27
  • 1
    @MaximEgorushkin: It says you're in UB land if you add declarations to `std`. There is no exception for duplicate declarations and therefore they're formally forbidden in defined, conforming C++ code. – Pixelchemist Apr 13 '16 at 10:29
  • @Pixelchemist _There is no exception for duplicate declaration_ - this statement is incorrect. See 7.1.3: _A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does... In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers._ – Maxim Egorushkin Apr 13 '16 at 10:37
  • @MaximEgorushkin: My statement is correct. Your quote just says that you can redeclare/redefine identical types in non-class scope. It does NOT lift the rule that you are *not allowed* to add declarations to `namespace std`. – Pixelchemist Apr 13 '16 at 10:42
  • 2
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/109031/discussion-between-pixelchemist-and-maxim-egorushkin). – Pixelchemist Apr 13 '16 at 10:45
  • @Pixelchemist I don't see anyone adding anything to the namespace `std` here. – Otomo Apr 13 '16 at 10:51
  • 6
    While that's a possible definition of `size_t`, this doesn't answer the OP's real question: it's as if I asked for the header where `FILE` is declared and you'd suggest to write my own one. – edmz Apr 13 '16 at 11:37
  • @black Most generalizations are incorrect. Yours is no exception. http://stackoverflow.com/a/36504750/412080 – Maxim Egorushkin Apr 13 '16 at 11:39
  • @MaximEgorushkin I don't see how it couldn't apply to this case. If one asks where to buy an hammer, suggesting how to craft one yourself is beyond the point of the question; notice I haven't said it's incorrect, it's simply outside the scope. – edmz Apr 13 '16 at 11:43
  • 4
    Downvoting, as while the post does not explicity put `size_t` in `namespace std`, the OP's question was about getting access to `std::size_t`. So it either does not answer the OP's question, or advises UB in order to do it. (Injecting such a typedef into `namespace std` is a declaration, and you cannot add such a declaration to namespace `std`.) Your insistence that this is legal is not relevant: even if you where correct, the standard would be *at least* ambiguous in it being UB, and adding ambiguously UB to code is almost as bad as unambiguously UB, barring large payoff. – Yakk - Adam Nevraumont Apr 13 '16 at 18:01
  • @Yakk There were numerous examples in the past when the standard was underspecified. E.g. people treated `std::string::data()` as contiguous when the standard did not require or guarantee this quality. Based on the historical precedents, and the requirements of the standard layed out in this post, the likelihood of this being UB is 0. – Maxim Egorushkin Apr 13 '16 at 18:37
  • 2
    @MaximEgorushkin You are using UB in a way that seems to line up with "crash" or "segfault", not "resulting in a program whose behavior is not specified by the standard". It is *intended* that adding symbols to `std` other than in a few narrow situations *should not be done* by user-side code. This is not an underspecification. You seem to be arguing "sure, the standard says not to do it, but do it anyway, what is the harm". That is fundamentally different than "the standard has an error". Finally, assuming `std::string::data()` was contiguous *has a large payoff*, your suggestion *has none*. – Yakk - Adam Nevraumont Apr 13 '16 at 18:45
  • @Yakk We agree to disagree agreeably. – Maxim Egorushkin Apr 13 '16 at 18:47
  • @FrédéricHamidi Uh, this isn't "perfectly correct." It (a) doesn't answer the question (which was: "which header?") and (b) advocates for UB. – Barry Apr 13 '16 at 18:55
  • 1
    @Barry, okay, maybe just *correct* then. At the time I landed here, this answer was standing at `-7` (presumably) because people wouldn't understand that `decltype(sizeof(int))` was basically `size_t`, not `int`. Other nitpicking matters were not in my perimeter. – Frédéric Hamidi Apr 13 '16 at 21:15
  • @FrédéricHamidi I wasn't objecting to your use of the word perfectly, I was objecting to your use of the word correct. – Barry Apr 13 '16 at 21:38
  • 1
    @Barry It is not established that this is incorrect. Despite opposing opinions. – Maxim Egorushkin Apr 13 '16 at 21:43
  • 3
    There aren't valid opposing opinions. There's the @Yakk (et al) supported argument that adding this declaration to `std` is UB. And there's you just disagreeing with that. All to argue for an answer that *at best* solves no problem anyway and is just trying to be clever. Best-case, you're right (and you're not), and this is a bad answer. Worst-case, this is just wrong. – Barry Apr 13 '16 at 22:26
  • "The standard bans adding new declarations and definitions into namespace std" ... You're still confused I'm afraid. The standard does **not** say that "[t]he behavior of a C++ program is undefined if it adds [**new**] declarations or definitions [...]" but it says that "[t]he behavior of a C++ program is **undefined if it adds declarations or definitions** [...]". There is a difference between those two statements. The first would allow adding another `std::size_t` definition, the latter doesn't. – Pixelchemist Apr 15 '16 at 11:26
  • 3
    Although this seems like a massive waste of time and energy I was asked to comment. Technically, adding any declaration to namespace std is UB, unless otherwise specified. There is no "otherwise specified" that allows (re)declarations of `std::size_t`. But in this case it won't ever do anything wrong, because `decltype(sizeof 1)` **is** `std::size_t`. But I see no advantage to doing this rather than `#include ` (which is a tiny header). – Jonathan Wakely Apr 15 '16 at 12:41