#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.
mutable, we should think it asoperator()() constand the value captured as a non static variable. However, those 2 links don't explain why using double parenthesis will addconstquantifier to the reference type.decltype(variable)is different fromdecltype((variable))becausedecltypedirectly depends on the syntax of its argument expression. The mention ofdecltypein your quote says "stuff likeint f(int); int *p = nullptr; decltype(f(*p)) x = 0;doesn't crash, even thoughf(*p)looks like it calls for the lvalue-to-rvalue conversion (i.e. read) of*nullptr".decltypeof an rvalue expression gives eitherT&&orT(for xvalues or prvalues, resp.) None of thedecltypes are on rvalues.