C++でconstポインタとconst参照とconstポインタconst参照

先日イテレータの扱いで少し確認してみたが, 今度はポインタの扱いを確認してみた. 見た目は結構エゲつないが, ポインタもconst参照渡しできる.

int main()
{
  typedef int T;

  T x(10), y(5), z(1);

  T* Tptr(&x);
  T const* Tconstptr(&x); // == const T*
  T* const Tptrconst(&x);
  T const* const Tconstptrconst(&x); // == const T* const

  *Tptr = 20;
  //XXX: *Tconstptr = 20;
  *Tptrconst = 20;
  //XXX: *Tconstptrconst = 20;

  Tptr = &y;
  Tconstptr = &y;
  //XXX: Tptrconst = &y;
  //XXX: Tconstptrconst = &y;

  T*& Tptrref(Tptr);
  T* const& Tptrconstref(Tptr);
  T const* const& Tconstptrconstref(Tptr);
  //XXX: T const*& Tconstptrref(Tptr);
  T const*& Tconstptrref(Tconstptr);

  *Tptrref = 30;
  *Tptrconstref = 30;
  //XXX: *Tconstptrconstref = 30;
  //XXX: *Tconstptrref = 30;

  Tptrref = &z;
  //XXX: Tptrconstref = &z;
  //XXX: Tconstptrconstref = &z;
  Tconstptrref = &z;

  return 0;
}

上は全てgcc version 4.8.2で試した.

T型のconst参照を書く際に"T const&"か"const T&"のどちらに書くべきか(意味的には同じ)考えていたのだが, ポインタ("T*")のconst参照渡しの場合, "T* const&"と"const T*&"は意味が異なってしまうので, "T const&"と書く方がより一般性があるような気がしてきた.

typedef T* TP;
const TP& constTPref(Tptr);
*constTPref = 30;
//XXX: constTPref = &z;

興味深いことに, T型のポインタを一度typedefで定義してやれば"const TP&"のように書ける. ようするに, "const (T*)& == (T*) const&"か"(const T)*&"かの違いである.

こんなことを考え出すとC++は恐ろしいとか言われてしまうのかもしれない.

https://social.msdn.microsoft.com/Forums/ja-JP/24cd88de-2159-4e8b-aee7-3fa30d8647db