Ske*_*een 13 c++ lambda c++11 c++14
如果一个lambda是无状态的,也就是说,如果它捕获了任何东西,我将如何进行测试?我的猜测是使用带有函数指针重载或模板特化的重载解析?
int a;
auto l1 = [a](){ return 1; };
auto l2 = [](){ return 2; };
// test l1 and l2, get a bool for statelessness.
Run Code Online (Sandbox Code Playgroud)
Naw*_*waz 14
根据标准,如果lambda没有捕获任何变量,那么它可以隐式转换为函数指针.
基于此,我想出了一个is_stateless<>元函数,它告诉你lambda是否是无状态的.
#include <type_traits>
template <typename T, typename U>
struct helper : helper<T, decltype(&U::operator())>
{};
template <typename T, typename C, typename R, typename... A>
struct helper<T, R(C::*)(A...) const>
{
static const bool value = std::is_convertible<T, R(*)(A...)>::value;
};
template<typename T>
struct is_stateless
{
static const bool value = helper<T,T>::value;
};
Run Code Online (Sandbox Code Playgroud)
这是测试代码:
int main()
{
int a;
auto l1 = [a](){ return 1; };
auto l2 = [](){ return 2; };
auto l3 = [&a](){ return 2; };
std::cout<<std::boolalpha<<is_stateless<decltype(l1)>::value<< "\n";
std::cout<<std::boolalpha<<is_stateless<decltype(l2)>::value<< "\n";
std::cout<<std::boolalpha<<is_stateless<decltype(l3)>::value<< "\n";
}
Run Code Online (Sandbox Code Playgroud)
输出:
false
true
false
Run Code Online (Sandbox Code Playgroud)
在线演示.
根据§5.1.2/ 6
没有lambda-capture的非泛型lambda表达式的闭包类型有一个公共的非虚拟非显式const转换函数指向函数,C++语言链接(7.5)具有相同的参数和返回类型.闭包类型的函数调用操作符.此转换函数返回的值应为函数的地址,该函数在调用时与调用闭包类型的函数调用运算符具有相同的效果.对于没有lambda-capture的通用lambda,闭包类型具有指向函数的公共非虚拟非显式const转换函数模板.
如果它是转化为函数指针,然后MAYBE它有没有捕获任何(无状态).在行动:
int v = 1;
auto lambda1 = [ ]()->void {};
auto lambda2 = [v]()->void {};
using ftype = void(*)();
ftype x = lambda1; // OK
ftype y = lambda2; // Error
Run Code Online (Sandbox Code Playgroud)
您还可以使用std::is_convertible:
static_assert(is_convertible<decltype(lambda1), ftype>::value, "no capture");
static_assert(is_convertible<decltype(lambda2), ftype>::value, "by capture");
Run Code Online (Sandbox Code Playgroud)
#include <type_traits> // std::true_type, std::false_type
#include <utility> // std::declval
template<typename Lambda>
auto is_captureless_lambda_tester(int)
-> decltype( +std::declval<Lambda>(), void(), std::true_type {} );
template<typename Lambda>
auto is_captureless_lambda_tester(long)
-> std::false_type;
template<typename Lambda>
using is_captureless_lambda = decltype( is_captureless_lambda_tester<Lambda>(0) );
Run Code Online (Sandbox Code Playgroud)
不适用于多态lambda,需要作为参数为闭包类型的前提条件.(例如is_captureless_lambda<int>是std::true_type).
| 归档时间: |
|
| 查看次数: |
2275 次 |
| 最近记录: |