目前我正在学习并行编程和元编程,我很难对捕获变量的lambda进行编译时检查。
假设我们有这样的代码:
#include <type_traits>
#include <functional>
#include <iostream>
int main(){
auto non_capture = [](){
std::cout<<"this lambda is not capturing!"<<std::endl;
};
auto capture = [&](){
std::cout<<"this lambda is capturing"<<std::endl;
};
//value is true for this one
static_assert(std::is_convertible<decltype(non_capture), std::function<void()>>::value, "message1");
//i need help for this
static_assert(is_lambda_that_captures<decltype(capture)>::value, "this is some error message");
}
我需要帮助来定义is_lambda_that_captures类型特征,这样我才能传递第二个静态断言。我该怎么做呢?
有一个针对最新标准的解决方案非常受欢迎(当前最新版本是c++17) :)
发布于 2018-05-31 19:02:04
对于C++17,您可以利用最新的特性:std::is_invocable
。它对于捕获和非捕获lambda都应该可以很好地工作:
static_assert(std::is_invocable_v<decltype(noncapture)>,"Error?!");
static_assert(std::is_invocable_v<decltype(capture)>,"Error?!");
当然,它也适用于函数指针、std::function
和所有可访问operator()
的对象。如果你只想检测lambdas (我看不出它有多大用处),你需要更多的特征魔法。
发布于 2018-05-31 18:55:41
这是我的解决方案。它依赖于两个原则:
#include <type_traits>
#include <functional>
#include <iostream>
template<class T, class Ret, class...Args>
struct is_non_capture_lambda : std::is_convertible<T, Ret (*)(Args...)>
{
};
template<class T, class Ret, class...Args>
struct is_capture_lambda
{
static constexpr auto convertible = std::is_convertible<T, std::function<Ret(Args...)>>::value;
using type = bool;
static constexpr auto value = convertible && !is_non_capture_lambda<T, Ret, Args...>::value;
};
int main(){
auto non_capture = [](){
std::cout<<"this lambda is not capturing!"<<std::endl;
};
auto capture = [&](){
std::cout<<"this lambda is capturing"<<std::endl;
};
//value is true for this one
static_assert(is_non_capture_lambda<decltype(non_capture), void>::value, "message1");
//i need help for this
static_assert(is_capture_lambda<decltype(capture), void>::value, "this is some error message");
}
发布于 2018-05-31 18:56:24
首先,请注意
static_assert(
std::is_convertible<decltype(capture), std::function<void()>>::value,
"msg");
也会通过。任何lambda都可以转换为适当类型的std::function
。捕获lambda和非捕获lambda之间的区别在于,非捕获lambda可以转换为指向函数的指针。所以:
static_assert(
std::is_convertible<decltype(non_capture), void (*)()>>::value,
"msg");
都会过去,但是
static_assert(
std::is_convertible<decltype(capture), void (*)()>>::value,
"msg");
都会失败。您可以使用std::is_class
区分非捕获的lambda和实际的函数指针(但我想不出您为什么要这样做)。
https://stackoverflow.com/questions/50622379
复制相似问题