[Bug c++/85149] New: False branch of if constexpr instantiated in generic lambda
barry.revzin at gmail dot com
gcc-bugzilla@gcc.gnu.org
Sat Mar 31 21:54:00 GMT 2018
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85149
Bug ID: 85149
Summary: False branch of if constexpr instantiated in generic
lambda
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: barry.revzin at gmail dot com
Target Milestone: ---
On latest trunk (8.0.1), the following compiles. But with -DBUG it doesn't:
template <typename T> struct is_void { static constexpr bool value = false; };
template <> struct is_void<void> { static constexpr bool value = true; };
template<typename S, typename T>
constexpr decltype(auto) pipeline(S source, T target)
{
return [=](auto... args)
{
if constexpr(false
#ifdef BUG
&& is_void<decltype(source(args...))>::value
#endif
)
{
source(args...);
return target();
} else {
return target(source(args...));
}
};
}
int main() {
pipeline([]{ return 10; },
[](int val){ return val * 10; });
}
With -DBUG, the error is:
prog.cc: In instantiation of 'constexpr decltype(auto) pipeline(S, T) [with S =
main()::<lambda()>; T = main()::<lambda(int)>]':
prog.cc:25:45: required from here
prog.cc:16:26: error: no match for call to '(const main()::<lambda(int)>) ()'
return target();
~~~~~~^~
prog.cc:16:26: note: candidate: 'int (*)(int)' <conversion>
prog.cc:16:26: note: candidate expects 2 arguments, 1 provided
prog.cc:25:24: note: candidate: 'main()::<lambda(int)>'
[](int val){ return val * 10; });
^
prog.cc:25:24: note: candidate expects 1 argument, 0 provided
-----------------
Wrapping source and target into an aggregate instead gets you an ICE on gcc 7.3
(https://godbolt.org/g/WvzuCs):
template <typename T> struct is_void { static constexpr bool value = false; };
template <> struct is_void<void> { static constexpr bool value = true; };
template <typename S, typename T>
struct pair {
S first;
T second;
};
template <typename S, typename T> pair(S, T) -> pair<S,T>;
template<typename S, typename T>
constexpr decltype(auto) pipeline(S&& source, T&& target)
{
return [callables = pair{source, target}](auto... args)
{
auto& [source, target] = callables;
using source_return = decltype(source(args...));
if constexpr(false && is_void<source_return>::value)
{
source(args...);
return target();
}
};
}
void foo()
{
auto s = []{ return 42; };
auto t = [](int){};
auto p = pipeline(s, t);
p();
}
More information about the Gcc-bugs
mailing list