This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/71105] New: [6 regression] lambas with default captures improperly have function pointer conversions
- From: "Casey at Carter dot net" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 13 May 2016 15:36:43 +0000
- Subject: [Bug c++/71105] New: [6 regression] lambas with default captures improperly have function pointer conversions
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71105
Bug ID: 71105
Summary: [6 regression] lambas with default captures improperly
have function pointer conversions
Product: gcc
Version: 6.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: Casey at Carter dot net
Target Milestone: ---
Created attachment 38483
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38483&action=edit
Minimal test case
N4582 [expr.prim.lambda]/7 says:
The closure type for a non-generic lambda-expression with no lambda-capture has
a conversion function to pointer to function with C++ language linkage (7.5)
having the same parameter and return types as the closure typeâs function call
operator. ... For a generic lambda with no lambda-capture, the closure type has
a conversion function template to pointer to function. The conversion function
template has the same invented template-parameter-list, and the pointer to
function has the same parameter types, as the function call operator template.
...
So all of:
static_cast<void(*)()>([]{});
static_cast<void(*)(int)>([](auto){});
static_cast<float(*)(float)>([](auto x){ return x; });
should compile. These should all be ill-formed since the lambdas have
lambda-captures:
static_cast<void(*)()>([i]{});
static_cast<void(*)()>([=]{});
static_cast<void(*)()>([&]{});
static_cast<void(*)(int)>([i](auto){});
static_cast<void(*)(int)>([=](auto){});
static_cast<void(*)(int)>([&](auto){});
static_cast<float(*)(float)>([i](auto x){ return x; });
static_cast<float(*)(float)>([=](auto x){ return x; });
static_cast<float(*)(float)>([&](auto x){ return x; });
clang (tested 3.4 - 3.9, all versions that implement generic lambdas) diagnoses
all of these conversions as ill-formed; gcc (4.9.0 - 6.1.0, again all versions
that implement generic lambdas) diagnoses only those with explicit captures.
This issue is significant when a library composes function objects via private
inheritance to take advantage of the empty base optimization and it adapts a
(possibly) underconstrained generic lambda to a different/larger valid space of
parameter types. For example, from range-v3:
#include <type_traits>
template <class F>
struct indirected : F {
indirected(F f) : F(f) {}
template <class I>
auto operator()(I i) -> decltype(std::declval<F&>()(*i)) {
return static_cast<F&>(*this)(*i);
}
};
int main() {
auto f = [=](auto i) { return i + i; };
auto i = indirected<decltype(f)>{f};
static_assert(std::is_same<decltype(i(std::declval<int*>())), int>(),
"");
}
This program compiles correctly with the GCC 4.9 and 5 series compilers, 6.1
diagnoses the static_assert line (See
http://melpon.org/wandbox/permlink/yy61pk0iJRfUVBya):
prog.cc: In instantiation of 'main()::<lambda(auto:1)> [with auto:1 = int*]':
prog.cc:13:24: required by substitution of 'template<class auto:1>
main()::<lambda(auto:1)>::operator decltype
(((main()::<lambda(auto:1)>)0u).operator()(static_cast<auto:1>(<anonymous>)))
(*)(auto:1)() const [with auto:1 = int*]'
prog.cc:15:63: required from here
prog.cc:13:37: error: invalid operands of types 'int*' and 'int*' to binary
'operator+'
auto f = [=](auto i) { return i + i; };
~~^~~