9

A scalar type is defined as

Trait class that identifies whether T is a scalar type. A scalar type is a type that has built-in functionality for the addition operator without overloads (arithmetic, pointer, member pointer, enum and std::nullptr_t).

It inherits from integral_constant as being either true_type or false_type, depending on whether T is a scalar type, no matter its const and/or volative qualification.

It means pointer is scalar type.

Now if we go to definition of literal type:

A type is a literal type if it is:

  • a scalar type; or
  • a reference type; or
  • an array of literal type; or -a class type (Clause 9) that has all of the following properties:
    • it has a trivial destructor,
    • every constructor call and full-expression in the brace-or-equal-initializers for non-static data members (if any) is a constant expression (5.19),
    • it is an aggregate type (8.5.1) or has at least one constexpr constructor or constructor template that is not a copy or move constructor, and
    • all of its non-static data members and base classes are of literal types.

Now, combining above 2 statements, it means pointer is literal type. However pointer can not be constexpr. can someone please clarify?

further see following code:

int a = 7;
constexpr int *pointer1 = &a;
int main ()
{
  int b = 4;
  constexpr int *pointer2 = &b;
}

pointer1 is fine but pointer 2 gives error. does that mean pointer to global is fine but to automatic variable is not? Does standard mention this anywhere ?

code707
  • 1,663
  • 1
  • 8
  • 20
  • 3
    "However pointer can not be constexpr." -- Are you sure about that? –  May 22 '18 at 11:24
  • 2
    Have a look at [SO: constexpr initializing with pointers](https://stackoverflow.com/a/13502591/7478597). Without deeper knowledge, but the answer looks for me that pointers _can_ be `constexpr`. – Scheff's Cat May 22 '18 at 11:24
  • 2
    Please don't change your question in such a way that existing answers are invalidated. As it stands, both answers just appear to repeat what you added into your question, even though they answered the question you originally asked. –  May 22 '18 at 11:39
  • sorry about that.. there was no way to add code as comment of an answer .. – code707 May 22 '18 at 11:40
  • Answer came when i was modifying question – code707 May 22 '18 at 11:41

2 Answers2

13

Pointers are literal types. They can be constexpr under certain conditions:

[expr.const] 6

... [a pointer is constexpr if] it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value.

(Where "object with static storage duration" means a global or static object, or a subobject of such object.)

A demo:

int x;

int main()
{
    constexpr int *ptr = &x; // Compiles.

    // Doesn't compile: `error: '& foo' is not a constant expression`
    // int foo;
    // constexpr int *bar = &foo;
}

Apparently GCC (with -pedantic-errors -std=c++11/14/17) happily accepts out-of-range constexpr pointer arithmetic: constexpr int *ptr = &x - 10;, which seems like a bug to me.

Community
  • 1
  • 1
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • I get what you mean, but it's not quite right. In `int x; constexpr int *p = &x + 1;`, `p` is not null and does not point to a global or static object. –  May 22 '18 at 11:27
  • @hvd Point taken. Is it better now? – HolyBlackCat May 22 '18 at 11:29
  • 1
    Yes, that's better, with the regular caveat that undefined behaviour renders an expression non-constant, so `int x; constexpr int *p = &x + 2;` is not okay. For completeness, they can also point to functions, when you're dealing with pointer-to-function types. –  May 22 '18 at 11:32
  • maybe "the address past the end of such an object" applies to both ends. anyway, that's likely a quote from draft, which is "incomplet and incorrekt" – Swift - Friday Pie May 22 '18 at 11:59
  • 1
    @Swift-FridayPie I assume *"the address past the end of such an object"* means "exactly one byte past the actual end (not beginning)". And the quote was there at least since C++14 and wasn't changed much... – HolyBlackCat May 22 '18 at 16:40
  • @HolyBlackCat then I don't get why they didn't says so, because the written idea after translation to many languages (even in head), including mine native, sounds exactly as I offered: end would mean either end, and "past" as indefinite distance :P – Swift - Friday Pie May 22 '18 at 20:13
3

Yes they are literals; yes they can be constexpr. To demonstrate:

constexpr int* foo=0;

int x = 7;

constexpr int* ptr=&x;

int main(){}
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524