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