4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[C++11] ref-qualifierとメンバ関数とthis

Last updated at Posted at 2014-09-03

C++11ではクラスのメンバ関数をref-qualifier修飾できる。
メンバ関数に対するref-qualifierは、メンバ関数の暗黙のパラメタ(*thisに対応する)に対するref-qualifierとなる。
ただし、メンバ関数がref-qualifier修飾されていない場合、暗黙のパラメタはlvalue-reference修飾される。(N3337 13.3.1 第4段落)

struct foo
{
  void f() &; //1
  void f() &&; //2
};

foo a;
a.f(); //1が呼ばれる
foo().f(); //2が呼ばれる

この機能はmoveセマンティクスをより多くのシーンで使うために導入された。
ところで、この規格の元でC++11のオーバーロード解決の仕組みを用いると、既存のコードが動かなくなる。
なぜなら、lvalue-referenceはrvalueを束縛できないからだ。
すなわち

struct foo
{
  void f() &;
};

foo().f(); //rvalueはlvalue-referenceで束縛できない

struct hoge
{
 void f() const&;
}; 

hoge().f(); //const-lvalue-referenceならばできる。

この規格の変更はあまりにも多くの既存のコードを破壊するので、次の例外が追加された。

ref-qualifier修飾されていないメンバ関数のオーバーロード解決においてのみ、const修飾されていなくても、rvalueを暗黙のlvalue-referenceパラメタに束縛できる。(N3337 13.3.1 第5段落)

struct foo
{
 void f() &;
};

foo().f() ; //今やちゃんとfoo::fが呼ばれる。

ところで、アルティメットメタプログラマー諸兄ならば、&と&&が違うだけの似たようなコードを2つ書くよりも、メタプログラミングによるスリム化を好むだろう。

ところが、恐らくそれはできない。
なぜならば、呼び出し元のクラスオブジェクトについての情報はthisを通しとのみ入ってくるが、*thisは常にlvalueである。従って、decltypeを使って、ref-qualifierを引っ張りだす事はできない。

悲しい。

もし、ref-qualifier修飾されていないメンバ関数内で呼び出し元のクラスオブジェクトの型を取得する方法を知っている人がいたら教えてほしい。

追記:なぜか括弧が消えていたので直した。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?