ラムダがステートレスかどうか、つまり何かをキャプチャするかどうかをテストするにはどうすればよいですか? 私の推測では、関数ポインターのオーバーロードまたはテンプレートの特殊化でオーバーロードの解決を使用していますか?
int a;
auto l1 = [a](){ return 1; };
auto l2 = [](){ return 2; };
// test l1 and l2, get a bool for statelessness.
§ 5.1.2/6 による
lambda-capture のない非ジェネリック lambda-expression のクロージャー型には、C++ 言語リンケージ (7.5) を持つ関数へのポインターへの public 非仮想非明示的な const 変換関数があり、同じパラメーターと戻り値の型を持ちます。クロージャー型の関数呼び出し演算子。この変換関数によって返される値は、呼び出されたときにクロージャー型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。ラムダ キャプチャのないジェネリック ラムダの場合、クロージャ型には、関数へのポインタへの public 非仮想非明示的な const 変換関数テンプレートがあります。
関数へのポインターに変換できる場合は、何もキャプチャしない (ステートレス) 必要があるかもしれません。実際に:
int v = 1;
auto lambda1 = [ ]()->void {};
auto lambda2 = [v]()->void {};
using ftype = void(*)();
ftype x = lambda1; // OK
ftype y = lambda2; // Error
次のものも使用できますstd::is_convertible
。
static_assert(is_convertible<decltype(lambda1), ftype>::value, "no capture");
static_assert(is_convertible<decltype(lambda2), ftype>::value, "by capture");
Boost.TypeTraitsis_stateless
は、なんらかの理由であまりドラマがなくても仕事をしているようです:
#include<boost/type_traits.hpp>
#include<cassert>
int main(){
auto l1 = [a](){ return 1; };
auto l2 = [](){ return 2; };
auto l3 = [&a](){ return 2; };
assert( boost::is_stateless<decltype(l1)>::value == false );
assert( boost::is_stateless<decltype(l2)>::value == true );
assert( boost::is_stateless<decltype(l3)>::value == false );
}
boost::is_stateless
他の条件の単純な組み合わせであり、私が推測する標準的な型特性の観点から表現できます。
::boost::is_stateless =
::boost::has_trivial_constructor<T>::value
&& ::boost::has_trivial_copy<T>::value
&& ::boost::has_trivial_destructor<T>::value
&& ::boost::is_class<T>::value
&& ::boost::is_empty<T>::value
に基づいて他の回答を確認してくださいsizeof
: https://stackoverflow.com/a/34873353/225186