Lambda capture as const reference?

后端 未结 8 1692
春和景丽
春和景丽 2020-11-30 19:33

Is it possible to capture by const reference in a lambda expression?

I want the assignment marked below to fail, for example:

#include 

        
相关标签:
8条回答
  • 2020-11-30 20:06

    Using a const will simply have the algorithm ampersand set the string to it's original value, In other words, the lambda won't really define itself as parameter of the function, though the surrounding scope will have an extra variable... Without defining it though, it wouldn't define the string as the typical [&, &best_string](string const s) Therefore, its most likely better if we just leave it at that, trying to capture the reference.

    0 讨论(0)
  • 2020-11-30 20:07

    Use clang or wait until this gcc bug is fixed: bug 70385: Lambda capture by reference of const reference fails [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70385]

    0 讨论(0)
  • 2020-11-30 20:08

    I guess if you're not using the variable as a parameter of the functor, then you should use the access level of the current function. If you think you shouldn't, then separate your lambda from this function, it's not part of it.

    Anyway, you can easily achieve the same thing that you want by using another const reference instead :

    #include <cstdlib>
    #include <vector>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    int main()
    {
        string strings[] = 
        {
            "hello",
            "world"
        };
        static const size_t num_strings = sizeof(strings)/sizeof(strings[0]);
    
        string best_string = "foo";
        const string& string_processed = best_string;
    
        for_each( &strings[0], &strings[num_strings], [&string_processed]  (const string& s)  -> void 
        {
            string_processed = s;    // this should fail
        }
        );
        return 0;
    }
    

    But that's the same as assuming that your lambda have to be isolated from the current function, making it a non-lambda.

    0 讨论(0)
  • 2020-11-30 20:10

    In c++14 using static_cast / const_cast:

    [&best_string = static_cast<const std::string&>(best_string)](const string& s)
    {
        best_string = s; // fails
    };
    

    DEMO


    In c++17 using std::as_const:

    [&best_string = std::as_const(best_string)](const string& s)
    {
        best_string = s; // fails
    };
    

    DEMO 2

    0 讨论(0)
  • 2020-11-30 20:11

    const isn't in the grammar for captures as of n3092:

    capture:
      identifier
      & identifier
      this
    

    The text only mention capture-by-copy and capture-by-reference and doesn't mention any sort of const-ness.

    Feels like an oversight to me, but I haven't followed the standardization process very closely.

    0 讨论(0)
  • 2020-11-30 20:15

    I think you have three different options:

    • don't use const reference, but use a copy capture
    • ignore the fact that it is modifiable
    • use std::bind to bind one argument of a binary function which has a const reference.

    using a copy

    The interesting part about lambdas with copy captures is that those are actually read only and therefore do exactly what you want them to.

    int main() {
      int a = 5;
      [a](){ a = 7; }(); // Compiler error!
    }
    

    using std::bind

    std::bind reduces the arity of a function. Note however that this might/will lead to an indirect function call via a function pointer.

    int main() {
      int a = 5;
      std::function<int ()> f2 = std::bind( [](const int &a){return a;}, a);
    }
    
    0 讨论(0)
提交回复
热议问题