First some motivation:

I can never remember where the const or volatile specifiers goes in a declaration. For example:

volatile int* const x;

Is x a volatile pointer to constant data or a constant pointer to volatile data or a constant volatile pointer to "normal" data.........

So my gut reaction to fix this situation (other than just memorizing the cases) would be to make these templates:

template<typename T>
using const_t = const T;
template<typename T>
using volatile_t = volatile T;
template<typename T>
using cv_t = const volatile T;

Then you would use it like this:

const_t<volatile_t<int>*> x;  //constant pointer to volatile data
const_t<cv_t<int>*> y; //constant pointer to constant and volatile data
const_t<int*> z;  //constant pointer to normal data

Does this seem like a good idea or should I just suck it up and learn all of the cases

  • \$\begingroup\$ Welcome to Code Review. Here we review real, working code. If you would like for us to review some code, please edit to add your working code/implementation. As it is, I don't think that your question is a good fit for this site. \$\endgroup\$ – Phrancis Oct 24 '17 at 17:50
  • \$\begingroup\$ @Phrancis The code that I posted does work and it is real.........The implementation is posted above..........I guess I am not sure what your concern about my question is. \$\endgroup\$ – DarthRubik Oct 24 '17 at 17:53
  • 1
    \$\begingroup\$ Please review the help center. It appears to be example code indeed, since your code by itself doesn't do anything useful. While you're at it, review the help center of Software Engineering as well, since they may just be more lenient for this question. \$\endgroup\$ – Mast Oct 24 '17 at 17:57
  • \$\begingroup\$ @Mast It does do useful things for me........it gives me three templates to use in my code.........I don't see how this is any different then someone writing say a logging class to use later in the their code........just because the logging class does not do anything useful on its own does not mean it does not do anything useful period. In the same way my code does nothing useful by itself, but it has to be used by other code....... \$\endgroup\$ – DarthRubik Oct 24 '17 at 18:02
  • \$\begingroup\$ I think this is obviously a real question with real code (something I would put in a utility namespace (if I agreed with it)). \$\endgroup\$ – Martin York Oct 25 '17 at 17:13

You're well on the way on making things unreadable for other people, personally I'd label this as "not a good idea". When someone sees volatile x they know what that means. When they look at const_t<int *> they have to find your typedef and parse it mentally. Just suck it up ...


Volatile and Const always bind left (unless they are the first (extreme left) symbol then they bind right).

So this

volatile int* const x;

// Is exactly the same as:
int volatile * const x;

Read the type is now easy. Just read from right to left.

Read like this

int volatile * const x;
 |     |     | |
 |     |     | (const
 |     |     ->pointer)
 |     |        to
 |     ------->(volatile

((int volatile) (* const))
  bind left       bind left

I think the rule is so simple to remember that you are just making things more complex and harder to read. Just place const and volatile on the right of the thing you want to attache it to.

 int const& getInt() const  

A function that returns a reference to a const int the function is const.

Note: The readability is one (of two) reasons why I buck tradition ("normal" usage) and Bjorne and don't put const first on the line.

  • \$\begingroup\$ Somebody voted it down! \$\endgroup\$ – Martin York Oct 25 '17 at 17:11

Not the answer you're looking for? Browse other questions tagged or ask your own question.