0
#include <iostream>

template <class T>
void print_type() {
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main () {
    float x, &r = x;
    std::cout << "capture by value" << std::endl;
    [=] {
        print_type<decltype(x)>();
        print_type<decltype((x))>();
        print_type<decltype(r)>();
        print_type<decltype((r))>();
    }();

    std::cout << "capture by reference" << std::endl;
    [&] {
        print_type<decltype(x)>();
        print_type<decltype((x))>();
        print_type<decltype(r)>();
        print_type<decltype((r))>();
    }();
}

The output of clang 10.0 is (GCC 10.0 has a bug):

capture by value
void print_type() [T = float]
void print_type() [T = const float &]
void print_type() [T = float &]
void print_type() [T = const float &]
capture by reference
void print_type() [T = float]
void print_type() [T = float &]
void print_type() [T = float &]
void print_type() [T = float &]

I wonder why decltype((x)) and decltype((r)) have a const qualifier when they are captured by value. When they are captured by reference, they don't have a const qualifier.

Any idea?

And what's the common use case of decltype((variable)) inside and outside lambda?

Edit#1:

Few flagged this as a duplicate of this.

The post doesn't explain why double parenthesis adds const to decltype's deduction.

HCSF
  • 2,387
  • 1
  • 14
  • 40
  • 1
    Does this answer your question? [Lambda: Why are captured-by-value values const, but capture-by-reference values not?](https://stackoverflow.com/questions/16764153/lambda-why-are-captured-by-value-values-const-but-capture-by-reference-values) or [C++0x lambda capture by value always const?](https://stackoverflow.com/questions/2835626/c0x-lambda-capture-by-value-always-const), etc. – underscore_d Jul 12 '20 at 09:01
  • "_GCC 10.0 has a bug_" What bug? – underscore_d Jul 12 '20 at 09:02
  • @underscore_d added the link to the bug report. – HCSF Jul 12 '20 at 09:05
  • @underscore_d thanks for your links. both links pointed out when lambda is captured by value without `mutable`, we should think it as `operator()() const` and the value captured as a non static variable. However, those 2 links don't explain why using double parenthesis will add `const` quantifier to the reference type. – HCSF Jul 12 '20 at 09:10
  • @KamilCuk would you mind elaborating? The link you attached doesn't mention such conversion... – HCSF Jul 12 '20 at 09:28
  • https://stackoverflow.com/questions/14115744/significance-of-parentheses-in-decltypec I made a typo in that comment. It's because "lvalue-to-rvalue" conversion (not the other way round). https://en.cppreference.com/w/cpp/language/implicit_conversion#Lvalue_to_rvalue_conversion Well, what's there to elaborate? A rvalue cannot be modified, so it's `const`. A lvalue can be modified so it's not `const`. Variable name is treated as variable type. Adding braces makes it an expression. – KamilCuk Jul 12 '20 at 09:30
  • 1
    @KamilCuk ? Neither conversion is relevant... `decltype(variable)` is different from `decltype((variable))` [because `decltype` directly depends on the syntax of its argument expression](http://eel.is/c++draft/dcl.type.decltype#1.3). The mention of `decltype` in your quote says "stuff like `int f(int); int *p = nullptr; decltype(f(*p)) x = 0;` doesn't crash, even though `f(*p)` looks like it calls for the lvalue-to-rvalue conversion (i.e. read) of `*nullptr`". `decltype` of an rvalue expression gives either `T&&` or `T` (for xvalues or prvalues, resp.) None of the `decltype`s are on rvalues. – HTNW Jul 12 '20 at 09:35

0 Answers0