yohhoyの日記

技術的メモをしていきたい日記

std::functionの戻り値型に関する小修正

C++1z(C++17)で修正される、std::functionクラステンプレートが扱う関数戻り値型にまつわる小さな問題。

// ラムダはintを返すがfunctionオブジェクトは戻り値型voidを扱う
std::function<void()> f = [](){ return 42; };
// C++11/14: 未定義動作(undefined behavior)
// C++1z: well-defiend

この問題は LWG 2420 にて取り扱われ、2015年5月現在のWorking Draft*1で修正適用された。

下記サンプルコードにおいて、オブジェクトf1のコンストラクタ呼び出しはその要件に違反しており、厳密にC++11標準規格に従うと未定義動作(undefined behavior)を引き起こす。これは、クラステンプレート引数に与えた関数シグネチャの戻り値型R = voidに対して、関数twiceの戻り値型intからの暗黙的な変換(int→void)が定義されないことによる。

#include <functional>

int twice(int x)
{ return x * 2; }

int main()
{
  std::function<int(int)> f0( twice );   // OK
  std::function<void(int)> f1( twice );  // NG: int→voidへ暗黙変換不可

  f0(42);
  f1(42);
}
std::functionの戻り値型に関する制約条件

関連URL