You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
struct foo {
foo non_const() { return {}; }
};
//...
with_all_optional_implementations<foo>(
[](auto make) {
const auto a = make();
auto f = [](auto &&x) { return x.non_const(); };
scelta::map(a, f);
}
);
results in this compiler error on GCC 7.2:
/home/simon/scelta/test/optional/optional_monadic.cpp: In instantiation of ‘main()::<lambda(auto:16)>::<lambda(auto:17&&)> [with auto:17 = const foo&; auto:16 = test::impl::maker_t<std::optional<foo> >]’:
/home/simon/scelta/include/scelta/./utils/optional_monadic.hpp:30:5: required by substitution of ‘template<class Optional, class T, class F> constexpr decltype ((scelta::is_nullopt(o) ? forward<decltype (def)>(def) : forward<decltype (f)>(f)(scelta::impl::access_optional(forward<decltype (o)>(o))))) scelta::map_or(Optional&&, T&&, F&&) [with Optional = const std::optional<foo>&; T = std::optional<foo>; F = main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<std::optional<foo> >]::<lambda(auto:17&&)>&]’
/home/simon/scelta/include/scelta/./utils/optional_monadic.hpp:39:5: required by substitution of ‘template<class Optional, class F> constexpr decltype (scelta::map_or(forward<decltype (o)>(o), std::decay_t<_Tp>{}, forward<decltype (f)>(f))) scelta::map(Optional&&, F&&) [with Optional = const std::optional<foo>&; F = main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<std::optional<foo> >]::<lambda(auto:17&&)>&]’
/home/simon/scelta/test/optional/optional_monadic.cpp:139:28: required from ‘main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<std::optional<foo> >]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:117:28: required from ‘test::with_all_optional_implementations(TF&&)::<lambda(auto:14)> [with auto:14 = test::impl::unpack_alternatives<test::impl::alternatives_t<foo> >::applier<std::optional>; TAlternative = foo; TF = main()::<lambda(auto:16)>]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:87:10: required from ‘void test::instantiate_with_all_optional_implementations(TF&&) [with TestCase = test::impl::unpack_alternatives<test::impl::alternatives_t<foo> >::applier; TF = test::with_all_optional_implementations(TF&&) [with TAlternative = foo; TF = main()::<lambda(auto:16)>]::<lambda(auto:14)>]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:116:80: required from ‘void test::with_all_optional_implementations(TF&&) [with TAlternative = foo; TF = main()::<lambda(auto:16)>]’
/home/simon/scelta/test/optional/optional_monadic.cpp:141:11: required from here
/home/simon/scelta/test/optional/optional_monadic.cpp:138:63: error: passing ‘const foo’ as ‘this’ argument discards qualifiers [-fpermissive]
auto f = [](auto &&x) { return x.non_const(); };
^
/home/simon/scelta/test/optional/optional_monadic.cpp:7:9: note: in call to ‘foo foo::non_const()’
foo non_const() { return {}; }
^~~~~~~~~
/home/simon/scelta/test/optional/optional_monadic.cpp: In instantiation of ‘main()::<lambda(auto:16)>::<lambda(auto:17&&)> [with auto:17 = const foo&; auto:16 = test::impl::maker_t<boost::optional<foo> >]’:
/home/simon/scelta/include/scelta/./utils/optional_monadic.hpp:30:5: required by substitution of ‘template<class Optional, class T, class F> constexpr decltype ((scelta::is_nullopt(o) ? forward<decltype (def)>(def) : forward<decltype (f)>(f)(scelta::impl::access_optional(forward<decltype (o)>(o))))) scelta::map_or(Optional&&, T&&, F&&) [with Optional = const boost::optional<foo>&; T = boost::optional<foo>; F = main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<boost::optional<foo> >]::<lambda(auto:17&&)>&]’
/home/simon/scelta/include/scelta/./utils/optional_monadic.hpp:39:5: required by substitution of ‘template<class Optional, class F> constexpr decltype (scelta::map_or(forward<decltype (o)>(o), std::decay_t<_Tp>{}, forward<decltype (f)>(f))) scelta::map(Optional&&, F&&) [with Optional = const boost::optional<foo>&; F = main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<boost::optional<foo> >]::<lambda(auto:17&&)>&]’
/home/simon/scelta/test/optional/optional_monadic.cpp:139:28: required from ‘main()::<lambda(auto:16)> [with auto:16 = test::impl::maker_t<boost::optional<foo> >]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:117:28: required from ‘test::with_all_optional_implementations(TF&&)::<lambda(auto:14)> [with auto:14 = test::impl::unpack_alternatives<test::impl::alternatives_t<foo> >::applier<boost::optional>; TAlternative = foo; TF = main()::<lambda(auto:16)>]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:91:10: required from ‘void test::instantiate_with_all_optional_implementations(TF&&) [with TestCase = test::impl::unpack_alternatives<test::impl::alternatives_t<foo> >::applier; TF = test::with_all_optional_implementations(TF&&) [with TAlternative = foo; TF = main()::<lambda(auto:16)>]::<lambda(auto:14)>]’
/home/simon/scelta/test/optional/../variant_test_utils.hpp:116:80: required from ‘void test::with_all_optional_implementations(TF&&) [with TAlternative = foo; TF = main()::<lambda(auto:16)>]’
/home/simon/scelta/test/optional/optional_monadic.cpp:141:11: required from here
/home/simon/scelta/test/optional/optional_monadic.cpp:138:63: error: passing ‘const foo’ as ‘this’ argument discards qualifiers [-fpermissive]
auto f = [](auto &&x) { return x.non_const(); };
^
/home/simon/scelta/test/optional/optional_monadic.cpp:7:9: note: in call to ‘foo foo::non_const()’
foo non_const() { return {}; }
^~~~~~~~~
make[3]: *** [test/CMakeFiles/test.optional.optional_monadic.dir/build.make:63: test/CMakeFiles/test.optional.optional_monadic.dir/optional/optional_monadic.cpp.o] Error 1
make[2]: *** [CMakeFiles/Makefile2:339: test/CMakeFiles/test.optional.optional_monadic.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:75: CMakeFiles/check.dir/rule] Error 2
make: *** [Makefile:175: check] Error 2
Expected behaviour: compile and run
This is because the implementation of map uses trailing return types, even in C++14 mode, which will cause the body of the lambda to be instantiated for the const-qualified overload, giving a hard error (it won't SFINAE). and_then has a similar issue. This could be solved by using auto return type deduction when compiling in C++14 mode.
It took me ages to work out why this broke for my implementation 😆
The text was updated successfully, but these errors were encountered:
Thanks for the report, I will look into this. Using automatic return type deduction would prevent SFINAE-friendliness... I wonder if there's a way of solving this without resorting to that.
I didn't find a better solution then just having separate versions for C++14 and 11, but if you do I'd love to hear it so that I can steal it for my impl 😆
Adding this code to
optional_monadic.cpp
:results in this compiler error on GCC 7.2:
Expected behaviour: compile and run
This is because the implementation of
map
uses trailing return types, even in C++14 mode, which will cause the body of the lambda to be instantiated for the const-qualified overload, giving a hard error (it won't SFINAE).and_then
has a similar issue. This could be solved by using auto return type deduction when compiling in C++14 mode.It took me ages to work out why this broke for my implementation 😆
The text was updated successfully, but these errors were encountered: