14

The Standard states, that nullptr is a pointer literal of type std::nullptr_t (2.14.7). And 18.2p9 defines nullptr_t by

namespace std {
  typedef decltype(nullptr) nullptr_t;
}

By 7.1.6.2p4 decltype(nullptr) is the type of the expression nullptr, which is by definition std::nullptr_t (since the expression nullptr is a prvalue). Substituting that into the definition of nullptr_t results in

typedef nullptr_t nullptr_t

On the other hand a typedef specifier does not introduce a new type, it's just a name for another existing type. So, what is exactly nullptr_t? I'm not able to comprehend these definitions.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
MWid
  • 4,429
  • 3
  • 20
  • 20

2 Answers2

10

It is implementation-specific. What is important is that (p. 18.2/9 of the C++11 Standard):

[...] The type for which nullptr_t is a synonym has the characteristics described in 3.9.1 and 4.10. [...]

As long as it behaves like the Standard specifies in those two paragraphs, it can be anything.

I believe the logical fallacy in your argument is that this:

By 7.1.6.2p4 decltype(nullptr) is the type of the expression nullptr, which is by definition std::nullptr_t (since the expression nullptr is a prvalue)

Does not mean that nullptr_t is not a type alias. For instance, if I define:

typedef decltype(42) foo;

I can say that the type of the expression:

42

Is foo. Yet, foo is just an alias for another type (int).

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • The standard explicitely states, that the type of `nullptr` is `std::nullptr_t`. So 18.2p9 comes down to `nullptr_t` is a synonym for itself. – MWid Jun 12 '13 at 15:40
  • 5
    @MWid: No, it is a synonym for something that is not specified by the standard. The fact that the type of `nullptr` is `std::nullptr_t` does not mean that `std::nullptr_t` cannot be an alias for some other type. That's what I tried to communicate in my answer (especially in the last example), although I have the feeling I haven't formulated it well – Andy Prowl Jun 12 '13 at 15:41
  • 7.1.3p1 states that typedef declares identifiers that can be used later for naming fundamental or compound types. Is `std::nullptr_t` a fundamental type? – MWid Jun 12 '13 at 15:47
  • @MWid: That's not what you should focus on. The point is that when you say "the type of `expr` is `X`", this does not mean that `X` cannot be a synonym for another type. So when the standard says "the type of `nullptr` is `nullptr_t`", this does not mean that `nullptr_t` cannot be a synonym for another type – Andy Prowl Jun 12 '13 at 15:48
  • 1
    Well, your answer convinced me that `nullptr_t` is a synonym for another type. And you say, that this type is not specified by the standard. In conclusion this means, that `nullptr_t` is a synonym for an unspecified fundamental type? – MWid Jun 12 '13 at 15:52
  • 3
    @MWid: Yes, `std::nullptr_t` is a fundamental type. It is also a scalar type and object type. – Howard Hinnant Jun 12 '13 at 15:53
  • Wouldn`t it be a better solution to add `nullptr_t` as simple-type-specifier to the core language? – MWid Jun 12 '13 at 15:56
  • Unfortunately, my knowledge is not sufficient to answer this last question, but I believe there are good reasons why the Committee decided to define it this way. Perhaps @HowardHinnant can provide an insight :) – Andy Prowl Jun 12 '13 at 15:58
  • 1
    @HowardHinnant I thought, I got it, but no. `nullptr_t` is a fundamental type and at the same time, it is an alias for another fundamental type otherwise the `typedef` definition would be ill-formed. So the core language contains an anspecified (and not mentioned) fundamental type. – MWid Jun 12 '13 at 16:05
  • 1
    I'm not terribly familiar with this area either. However N2431 may hold the answer to this question: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf – Howard Hinnant Jun 12 '13 at 16:16
  • @HowardHinnant: Thank you for the link, I think it does shed some light – Andy Prowl Jun 12 '13 at 16:24
  • 1
    @MWid: Perhaps one of the reasons is that introducing a new keyword would have been a problem for old programs that used the name `nullptr_t` (perhaps there aren't any, but hard to tell). Making `nullptr_t` a keyword would likely make those programs ill-formed. This way, you can use the `nullptr_t` name for your own purposes, and if you need to refer to the type of `nullptr` through a name, then you can use `std::nullptr_t` – Andy Prowl Jun 12 '13 at 16:26
  • 2
    I think it's more accurate to say that `std::nullptr_t` is a typedef (in ``) for the otherwise unnamed fundamental type of which `nullptr` is an instance. – Mooing Duck Jun 12 '13 at 17:02
  • 1
    Strictly speaking, I don't think that it is correct to say, that the type of the expression `42` is `foo`. The type of this expression is `int`, for which `foo` is another name. But `foo` itself is not a type. – MWid Jun 12 '13 at 17:53
  • @MWid: I see what you mean, but I'm not sure whether you should take it to that level of precision. IOW, since `foo` is a name for `int`, you *can* say that the type of `42` is `foo`. While it may be more precise saying that the type of `42` is `int`, it is not *wrong* to say that the type of `42` is `foo` - because you have defined `foo` as an alias for `int`, so they mean the same thing. – Andy Prowl Jun 12 '13 at 18:00
  • 3
    In few words: types are not their names. – R. Martinho Fernandes Jun 13 '13 at 09:48
  • I cannot find any of the references to the C++ standard that you have posted: 3.9.1 , 4.10 , 7.1.6.2p4 . Would you mind showing me where I can find these sections ? :/ – AymenTM Nov 10 '19 at 15:59
5

Internally there is an entity that is the null pointer constant type. It is one of the fundamental types.

The keyword, literal and expression nullptr has this type. decltype(nullptr) refers to this type.

However the name std::nullptr_t is not a keyword (not even a context-sensitive one), and so the name does not exist until declared. If you refer to the name std::nullptr_t without declaring it, it is an error, as for any undeclared name.

So although the type exists at the start of translation like any fundamental type, the name does not exist.

In fact there are other fundamental types that do not have a "single spelling", such as short int. A short int can be refered to as short, short int, signed short int, signed short, or any permutation thereof.

It is also not dissimilar to the relationship between the typeid operator (keyword), and the type of the typeid(...) expression, std::typeinfo. typeinfo is also not a keyword and the name does not exist before being declared.

Basically, you are conflating an entity (the null pointer constant type) with a name (std::nullptr_t)

If you ask why didn't the language designers specify nullptr_t and typeinfo as keywords, I would speculate that they are not common enough to risk a name collision with a user-defined name with the same spelling. Recall that such a collision would occur in any and all scopes.

Andrew Tomazos
  • 66,139
  • 40
  • 186
  • 319
  • 1
    Where is _null pointer constant type_ defined in the standard? – MWid Jun 12 '13 at 16:54
  • 2
    @MWid: It isn't explictly, I'm using the term for exposition to refer to the type of `nullptr`, as distinct from a C++ _name_ for that type. I agree that the standard could be clearer about the distinction, most of what I describe is an implicit consequence - but entities and names are distinguished in the preamble of clause 3. – Andrew Tomazos Jun 12 '13 at 17:09