17

Having just read:

Does "std::size_t" make sense in C++?

I realize using ::size_t is not standards-compliant (although supported by my compiler) when you #include <cstddef>. I want to comply with the standard, but I do not want to prepend std:: to all of my size_t's. So, what is the more customary/popular way to handle this:

  • write using std::size_t;?
  • include <stddef.h>?
  • just rely on compiler support?
  • something else?
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 2
    I find this question interesting, although as the CVers have _said_, it is primarily opinion-based. Perhaps asking "What is the least intrusive, but standard-compliant way"? – Tas Mar 14 '17 at 22:06
  • @Tas: I asked about what people use the most, so it's not opinion-based. I don't care about what's "best", it's all nitpicking anyway... I just want to follow the herd. – einpoklum Mar 14 '17 at 22:25
  • And how would you determine what people use the most from a set of answers? – juanchopanza Mar 14 '17 at 22:29
  • @juanchopanza: A single answer should be enough, by someone who's been around and has seen enough code to estimate what's the common practice. Empirical observation-based estimation != opinion. Although I will admit the voted-up answer doesn't quite do that. – einpoklum Mar 14 '17 at 22:35
  • Given how much code a single person can look at in their lifetime, any apparently authoritative answer is extremely likely to be an opinion. – juanchopanza Mar 14 '17 at 22:41
  • 1
    Virtually all code that uses size_t would be better off with an "int". But both the C and C++ committees have dragged us down this route. – Malcolm McLean Mar 14 '17 at 22:44
  • @MalcolmMcLean We wouldn't be better off at all. size_t has semantic meaning and is defined in a platform specific way. Also using int instead of size_t doesn't make sense in a single case. When you're using size_t for a situation where a signed int makes sense something's wrong. –  Mar 14 '17 at 22:49
  • 4
    @MalcolmMcLean's opinion is one that is not shared by the vast majority of C and C++ programmers. – Keith Thompson Mar 14 '17 at 22:51
  • 1
    Using "size_t" for an index variable is required, and also an unacceptable name. The implications of changing sizeof() were simply not thought through. – Malcolm McLean Mar 14 '17 at 22:52
  • 3
    @MalcolmMcLean: Using `size_t` for an index variable is not required. Any integral type can be used, as long as its range covers the range of indices. `size_t` is simply a type that's guaranteed to cover any possible range of indices. I presume when you say that the name is "unacceptable", you mean that you personally don't like it. I like it just fine. – Keith Thompson Mar 14 '17 at 22:56
  • I'd probably use `#include ` and `std::size_t`, but I don't claim that's either customary or popular. – Keith Thompson Mar 14 '17 at 22:58
  • 1
    @MalcolmMcLean: Link to an argument for this, shall we say, bold claim? – einpoklum Mar 14 '17 at 23:01
  • 1
    It's not bold at all, You have real values, integers, and strings. Most of the integers are counts of things in memory or indices into arrays or tables in memory. The obvious name for them is "int". – Malcolm McLean Mar 14 '17 at 23:07
  • @MalcolmMcLean: Perhaps we should just get rid of typedef, then. Or of unsigned types. Seriously, though, I just don't get what you're saying. I "have" all sorts of fundamental types, and I have semantics-laden typedefs over that. Please link to a more serious discussion of your point. – einpoklum Mar 15 '17 at 01:12
  • Because 'size_t' comes from multiple places, your readers will want to (and occasionally need to) know which 'size_t' you mean. Hence, my editor auto-magically prepends (or is it auto-completes?) i.e. "std::size_t" No effort for me, and readable for everyone. – 2785528 Mar 15 '17 at 02:42
  • @DOUGLASO.MOEN: No, `size_t` doesn't come from multiple places. If you mean multiple places in the standard library - well, that's true, but it's the same `size_t`. Can you show an example of `size_t` coming from multiple (widely-used) places? – einpoklum Mar 16 '17 at 17:04
  • @einpoklum Yes, multiple places in the standard library. – 2785528 Mar 17 '17 at 19:32
  • @DOUGLASO.MOEN: But it's all the same "place", or two places - either `::size_t` if it's the C standard library or `std::size_t` if it's the C++ flavor of it. – einpoklum Mar 17 '17 at 21:46

2 Answers2

11

You should specify it with the using directive.

using std::size_t;

Add it either to the global scope of each compilation unit, or to the local scopes if it would cause interference at the global scope.

stddef.h also works, as you noted, and honestly that method is not "worse" than this one. However, stddef.h is a backwards compatibility header, and it might be best to avoid relying on it in new code.

I prefer the using directive because it does not pollute the global namespace anywhere you don't need to, and does not rely on arbitrary compiler support of nonstandard behavior. Further, this is the generally accepted way to bring a type into a namespace when multiple options are otherwise possible, so it is not unique to the usage of size_t.

This isn't really something that a person can authoritatively answer. I've been a professional developer for 10 years, and have worked with C++ since 1998, but I will never see any statistically significant portion of the total C++ code that's been written. From what I have seen, there is plenty of code out there that still uses stddef.h, and it won't likely break anytime soon.

For new code, I prefer just typing the "std::" prefix everywhere, only applying the using directives when it becomes cumbersome or difficult to read. However, I recognize that this can be irritating for "inherited" code, which is where the file-scope using directives are better. If you have the time to properly refactor the inherited code, there's a good argument that you should do so, but it's very likely to involve more than just the size_t variables.

I should also mention that the C++ FAQ (item 27.5) mentions this concern as well here, where I got the impression they mostly recommend consistency with others on your team.

I want to note here that it is NOT good practice to apply "using namespace std" at the file scope, though this would also bring size_t into the global namespace. I will link the reason for that here.

I seem to have scared tuple_cat off (sorry), but I really did think his empirical method was good, so I'm trying to incorporate some changes to resolve my concerns with his answer. I tried searching github with the following modified queries, which admittedly still may have some issues:

A) "size_t" AND "stddef.h" language:c++
B) "std::size_t" AND "<cstddef>" language:c++
C) "size_t" AND "<cstddef>" AND NOT "std::size_t" language:c++
D) "size_t" AND "<cstddef>" AND "using namespace std" AND NOT "std::size_t" language:c++
E) "size_t" AND "<cstddef>" AND "using std::size_t" language:c++

I get the following:

  • A) 974,239 results (stddef.h approach)
  • B) 1,230,021 results (cstddef approach, with "std::" prefixes)
  • C) 469,721 results (cstddef approach, no prefixes)
  • D) 32,539 results (cstddef approach, "using namespace std", DON'T DO THIS!)
  • E) 27,080 results (method I recommend, "using std::size_t")

It's definitely not perfect, and I welcome criticism to make it better, but it appears that the method I recommend, as stated, is not the most popular. Based on the data, it appears that the most popular is using the "std::" prefixes on size_t (B), followed by including "stddef.h" (A). Luckily, the bad approach of (D) is not popular, but it appears that many people may be relying on other files/headers to bring size_t into the global namespace, or just hoping it's already there on the compiler (C).

Therefore, to "go with the herd", you should prepend everything with "std::". If you don't want to do that, then "stddef.h" is also in very common use, but my preference is still the using directive.

Community
  • 1
  • 1
Bob Miller
  • 603
  • 5
  • 12
  • So, actually the methodology is off, because people tend to use `std::` more in library code than in apps, and I think that's over-represented on GitHub. But - you seem to have gotten totally different numbers than @tuple_cat. – einpoklum Mar 15 '17 at 01:15
  • Fair enough, but I liked that his method was empirical and repeatable. It may be biased data, but I'm just happy to have data at all. I think the distinction between his numbers and mine stem from the fact that I'm trying to narrow my search to just the specific use of size_t, and the different usage types you described. – Bob Miller Mar 15 '17 at 01:26
5

So, what is the more customary/popular way to handle this:

Here's one way to determine that:

GitHub search for "std::size_t" in C++ code: 4,650,049 results.
GitHub search for "size_t" in C++ code: 24,835,033 results.

Similarly "#include <stddef.h>" gives 1,051,142 hits, while "#include <cstddef>" gives 2,099,971. A search for "using std::size_t;" gives only 50,057 results.

Just putting this out here, make your own conclusions.

Emil Laine
  • 41,598
  • 9
  • 101
  • 157
  • But how did they get `size_t`? – juanchopanza Mar 14 '17 at 22:41
  • The size_t result would come whether ::size_t was included from stddef.h or from a using directive, so this method does not distinguish between the two. Also, the apparent results between your first result and your second conflict: is not required to declare ::size_t. – Bob Miller Mar 14 '17 at 22:45
  • 2
    "using std::size_t" is not the only using directive that brings size_t into the namespace. Another way to do it would be "using namespace std", which I suspect is fairly common. Not criticizing here: you have an empirical method, I'm just trying to help poke holes you can try to plug to make the answer better. – Bob Miller Mar 14 '17 at 22:53
  • 2
    @BobMiller `using namespace std;` is usually bad practice and shouldn't be used globally. –  Mar 14 '17 at 22:55
  • 2
    @user2176127 I definitely agree. I mention it because it's a different way to bring size_t into the global namespace that would not be caught by the above search. Also, the problem with the #include searches is that includes more than just size_t, so it's difficult to say from those results whether the users are including it for the purpose of bringing size_t into the namespace or not. – Bob Miller Mar 14 '17 at 22:57
  • The fact the people use `size_t` rather than specifying `std::size_t` doesn't tell us exactly which option they chose among the ones I've listed... – einpoklum Mar 14 '17 at 23:03
  • @einpoklum The best way would be appending `std::`. With tools like Visual Assist X or ReSharper C++ this is fairly easy to do. A proper regex is capable of doing this as well. Everything else feels like beating around the bush. My 2cts –  Mar 14 '17 at 23:04
  • @user2176127 fair enough, as I mentioned I do think that's the best option for new code. I think it gets closer to fully refactoring the code, however, which leads to the question of where to stop refactoring. I was looking at it from the perspective of having code to maintain and wanting to make the minimal changes to make it portable. – Bob Miller Mar 14 '17 at 23:14
  • of course, [using namespace std;](https://github.com/search?utf8=%E2%9C%93&q=%22using%20namespace%20std;%22+language%3Ac%2B%2B&type=Code&ref=searchresults) is bad but **practice** ;) – Wolf Nov 17 '17 at 12:46