Crazy constexpr lambdas implementation article
它基本上归结为这种实现:
template<class F>
struct wrapper
{
//static_assert(std::is_empty<F>(), "Lambdas must be empty");
template<class... Ts>
decltype(auto) operator()(Ts&&... xs) const
{
return reinterpret_cast<const F&>(*this)(std::forward<Ts>(xs)...);
}
};
struct wrapper_factor
{
template<class F>
constexpr wrapper<F> operator += (F*)
{
return{};
}
};
struct addr_add
{
template<class T>
friend typename std::remove_reference<T>::type* operator+(addr_add, T &&t)
{
return &t;
}
};
#define STATIC_LAMBDA wrapper_factor() += true ? nullptr : addr_add() + []
使用
const constexpr auto add_one = STATIC_LAMBDA (/*i believe you can pass arguments here but i havent tried*/) -> bool
{
//do stuff
return stuff;
};
我有两个问题:
我需要注释掉static_assert,因为“std :: is_empty&lt; _Ty&gt;':没有合适的默认构造函数”,即使没有创建这个lambda的任何实例。谁知道为什么?
这是如何工作的?我跟着所有课程的流程,我明白了
a)这部分
true ? nullptr : addr_add() + [] your_lambda
返回我们想要lambda的类型的nullptr(进一步称为“correct_type”)
b)wrapper_factory将此nullptr作为correct_type,构造包装器。此包装器是默认初始化的。
c)operator()中的包装器将他被调用的参数(在/ * i相信... / *位置传递)转发给一个对象,该对象是“将此指针转换为correct_type的包装器”。
现在,要调用的例程实际传递的信息在哪里?我只能看到默认创建的空包装器,它被重新解释为某种lambda类型并通过()调用。
祝你好运
Marcin K。
答案 0 :(得分:0)
请考虑此代码
#include <type_traits>
template<class F>
struct wrapper
{
static_assert(std::is_empty<F>::value, "Lambdas must be empty");
template<class... Ts>
decltype(auto) operator()(Ts&&... xs) const
{
return reinterpret_cast<const F&>(*this)(std::forward<Ts>(xs)...);
}
};
struct wrapper_factor
{
template<class F>
constexpr wrapper<F> operator += (F*)
{
return{};
}
};
struct addr_add
{
template<class T>
friend typename std::remove_reference<T>::type *operator+(addr_add, T &&t)
{
return &t;
}
};
#define STATIC_LAMBDA wrapper_factor() += true ? nullptr : addr_add() + []
const constexpr auto add_one = STATIC_LAMBDA(auto x)
{
return x + 1;
};
int main()
{
int a = 1;
int b = add_one(a);
return 0;
}
因此,在MSVS2015中,add_one报告为constexpr wrapper<type> add_one = {}
但在主要内容中,add_one(a)
报告为int wrapper<lambda []auto (auto x)->auto>::operator() <int &>(int &xs) const
您可以看到*operator+
中的友元函数addr_add
返回指向lambda函数的指针。 lambda函数定义是隐含的。包装器struct operator()中的可变参数模板将模仿lambda参数。
这是你想知道的吗?