静态断言lambda捕获

时间:2018-05-31 10:40:19

标签: c++ c++17

我正在学习并行编程和元编程,我很难对编译时间进行检查,以获取捕获变量的lambda。

让我们说我们有这样的代码:

{{1}}

我需要帮助来定义 is_lambda_that_captures 类型特征,以便我可以传递第二个静态断言。我该怎么办?

获得最新标准的解决方案非常受欢迎(目前最新的是c ++ 17):)

3 个答案:

答案 0 :(得分:4)

这是我的解决方案。它依赖于两个原则:

  1. 非捕获lambda可以转换为函数指针。

  2. 所有lambda都可以转换为std :: function。

  3. #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");
    }
    

答案 1 :(得分:3)

对于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::functionoperator()可访问的所有对象。如果你只想检测lambdas(我没有看到太多用途),你将需要更多的特质魔法。

答案 2 :(得分:1)

首先,请注意

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和实际函数指针(但我不能想到您想要的原因)。