Core short C++ facts

Point of declaration

After difficult posts about the coroutines and before yet another one I decided to take a break and write about something easier instead. This time we will have a look at one of the aspects of the declarations namely – point of declaration.

So what is this point of declaration? Intuitively it’s a point in the source code, since when the name of the declared entity is taken into account by the compiler. Usually, the point of declaration is after declarator and before initializer.

Ok, but what does it mean in practice? Standard gives us two examples of the source codes:

int i = 42;
{
  int i = i;
}

I bet, that normally most of the C++ users will guess, that value of the i in the inner scope will be 42, but most probably this is not the case. If we split the statement into parts, then int i is a declarator and = i is initializer. Since declaration point is between them, it means, that the statement is declaring the value i and assigns its own value to itself. This of course results in the undefined behavior.

Another example of the code from the standard:

const int  i = 2;
{ int  i[i]; }

Now is it undefined behavior? It sure looks strange, but again following the mentioned rule the point of declaration is in fact in the place of the ;. This means, we are declaring an array of two integers named i.

Exceptions from the general rule

There are exceptions from the general rule, which are as follows:

Classes and enums have their point of declaration immediately after their name

This makes CRTP pattern possible:

struct TheOneRight : Singleton<TheOneRing>{/*...*/};
               // ^ here is the declaration point

Aliases points of declarations are immediately after the type they point to

struct Test;
        // ^ here is declaration point

void foo(){ using Test = Test; /*does nothing*/ }
                          // ^ here is the point of declaration

Enumerators point of declaration is after its complete definition

constexpr bool yes=true, no=false;
                //^        ^here are declaration points
enum class Decision{yes = yes, no = no};
                           //^        ^ here are declaration points
enum class Incremental{first = 10, second = first+1};
                           //    ^                 ^ declaration points

Functions declaration point is before its body

void stack_eater(unsigned i){stack_eater(++i);}
                         //^ here is the declaration point  

This allows to make recursive calls.

Template parameters’ declaration points are after the parameters are introduced

using T = unsigned char;
template<class T
  = T     // lookup finds the typedef name of unsigned char
  , T     // lookup finds the template parameter T
    N = 0> struct A { };

Summary

This is the first post of the short C++ facts series, that I am going to continue. In this post, we have learned what is the point of declaration and it’s consequences on the code’s behavior. If you want to support me, there is nothing more motivating than feedback and a kind word :). You can contact me at dawid.pilarski@<mydomain>.com. Cheers!


Bibliography

Liked it? Share it...

2 thoughts on “Point of declaration”

  1. “and it’s consequences on the code’s behavior” I’m not sure that you showed those consequences. Otherwise thanks for this inventory. Good to have it all in one place.

    1. Hello @VicDiesel and thank you for the first comment on my blog!

      I was trying to give a hint on the code’s behavior after every example (int i=i – gives undefined behavior, declaration point of the function – allows recursive calls).

      I do agree however, that the examples are far from being comprehensive. I will try better next time.

      Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.