Следующий код компилируется с помощью clang 6 и 7 и g ++ 7.2. Однако g ++ 8.2 отклоняет это, жалуясь, что error: ‘predicate’ is not captured
.
#include <utility>
#include <iostream>
template<bool b>
constexpr auto bool_c = std::bool_constant<b>{};
template<char... str>
struct string {
};
template<typename T>
constexpr bool is_bool_constant_like_v = (std::is_base_of_v<std::bool_constant<true>, T> ||
std::is_base_of_v<std::bool_constant<false>, T>);
constexpr auto index_if = [](auto predicate, auto &&tup) {
using predicate_t = decltype(predicate);
constexpr auto func = [](auto x) {
using predicate_return_t = decltype(predicate(std::declval<decltype(x)>()));
if constexpr (is_bool_constant_like_v<predicate_return_t>) {
return bool_c<predicate_return_t::value>;
}
};
// actual code here callinf func....
return 42;
};
int main() {
#ifdef __GLIBCPP__
std::printf("GLIBCPP: %d\n",__GLIBCPP__);
#endif
#ifdef __GLIBCXX__
std::printf("GLIBCXX: %d %d\n", _GLIBCXX_RELEASE, __GLIBCXX__);
#endif
//return 0;
constexpr auto abababa = string<'a', 'b', 'a', 'b', 'a'>{};
constexpr auto xxx = index_if([](auto x) constexpr { return bool_c<true>; }, abababa);
}
Проблема, похоже, заключается в использовании predicate
внутри decltype()
в L 18. Я думаю, это ошибка в g ++, или другие компиляторы ошибочны?
Интересно, что если я добавлю захват по умолчанию =
во вложенную лямбду, он снова не сможет скомпилироваться в g ++ - 8.2, но теперь жалуется, что predicate is not a constant expression
.
Очевидный обходной путь с использованием decltype(std::declval<predicate_t>(....)
работает. Так что я просто хотел знать, какой компилятор работает правильно?
Живой пример здесь