Skip to content

Commit

Permalink
Fix issue with generic lambdas in optional map
Browse files Browse the repository at this point in the history
Closes foonathan#60.
  • Loading branch information
foonathan committed May 4, 2018
1 parent 039969e commit 441f054
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
13 changes: 12 additions & 1 deletion include/type_safe/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,17 @@
#define TYPE_SAFE_RVALUE_REF
#endif

#ifndef TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
#if defined(__cpp_return_type_deduction) && __cpp_return_type_deduction >= 201304
/// \exclude
#define TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION 1
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION 1
#else
#define TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION 0
#endif
#endif

#ifndef TYPE_SAFE_USE_NOEXCEPT_DEFAULT

#if defined(__GNUC__) && __GNUC__ < 5
Expand Down Expand Up @@ -134,7 +145,7 @@ namespace type_safe
{
void on_disabled_exception() noexcept;
}
} // namespace type_safe::detail
} // namespace type_safe

#define TYPE_SAFE_THROW(Ex) (Ex, type_safe::detail::on_disabled_exception())
#define TYPE_SAFE_TRY if (true)
Expand Down
24 changes: 17 additions & 7 deletions include/type_safe/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ namespace type_safe
std::is_void<T>::value, void,
basic_optional<select_optional_storage_policy<
typename optional_storage_policy_for<T>::type, Fallback>>>::type;
}
} // namespace detail

/// An optional type, i.e. a type that may or may not be there.
///
Expand Down Expand Up @@ -222,7 +222,7 @@ namespace type_safe
return std::move(static_cast<detail::optional_storage<StoragePolicy>&>(*this).storage);
}

const storage&& get_storage() const && noexcept
const storage&& get_storage() const&& noexcept
{
return std::move(
static_cast<const detail::optional_storage<StoragePolicy>&>(*this).storage);
Expand Down Expand Up @@ -481,8 +481,10 @@ namespace type_safe
/// \exclude return
template <typename Func, typename... Args>
auto map(Func&& f, Args&&... args) TYPE_SAFE_LVALUE_REF
#if !TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
-> rebind<decltype(detail::map_invoke(std::forward<Func>(f), this->value(),
std::forward<Args>(args)...))>
#endif
{
using return_type = decltype(
detail::map_invoke(std::forward<Func>(f), value(), std::forward<Args>(args)...));
Expand All @@ -498,8 +500,10 @@ namespace type_safe
/// \exclude return
template <typename Func, typename... Args>
auto map(Func&& f, Args&&... args) const TYPE_SAFE_LVALUE_REF
#if !TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
-> rebind<decltype(detail::map_invoke(std::forward<Func>(f), this->value(),
std::forward<Args>(args)...))>
#endif
{
using return_type = decltype(
detail::map_invoke(std::forward<Func>(f), value(), std::forward<Args>(args)...));
Expand All @@ -515,8 +519,11 @@ namespace type_safe
/// \group map
/// \exclude return
template <typename Func, typename... Args>
auto map(Func&& f, Args&&... args) && -> rebind<decltype(
detail::map_invoke(std::forward<Func>(f), this->value(), std::forward<Args>(args)...))>
auto map(Func&& f, Args&&... args) &&
#if !TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
-> rebind<decltype(detail::map_invoke(std::forward<Func>(f), this->value(),
std::forward<Args>(args)...))>
#endif
{
using return_type = decltype(
detail::map_invoke(std::forward<Func>(f), value(), std::forward<Args>(args)...));
Expand All @@ -531,8 +538,11 @@ namespace type_safe
/// \group map
/// \exclude return
template <typename Func, typename... Args>
auto map(Func&& f, Args&&... args) const && -> rebind<decltype(
detail::map_invoke(std::forward<Func>(f), this->value(), std::forward<Args>(args)...))>
auto map(Func&& f, Args&&... args) const&&
#if !TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
-> rebind<decltype(detail::map_invoke(std::forward<Func>(f), this->value(),
std::forward<Args>(args)...))>
#endif
{
using return_type = decltype(
detail::map_invoke(std::forward<Func>(f), value(), std::forward<Args>(args)...));
Expand Down Expand Up @@ -888,7 +898,7 @@ namespace type_safe
}

/// \group value
const_rvalue_reference get_value() const && noexcept
const_rvalue_reference get_value() const&& noexcept
{
return std::move(*static_cast<const value_type*>(as_void()));
}
Expand Down
2 changes: 1 addition & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ set(source_files test.cpp
add_executable(type_safe_test debugger_type.hpp ${source_files})
target_link_libraries(type_safe_test PUBLIC type_safe)
target_include_directories(type_safe_test PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
set_property(TARGET type_safe_test PROPERTY CXX_STANDARD 11)
set_property(TARGET type_safe_test PROPERTY CXX_STANDARD 14) # some tests require 14

if(MSVC)
target_compile_definitions(type_safe_test PRIVATE TYPE_SAFE_TEST_NO_STATIC_ASSERT)
Expand Down
14 changes: 14 additions & 0 deletions test/optional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,20 @@ TEST_CASE("optional")
optional_ref<int> c_res2 = c.map(&foo::var);
REQUIRE(c_res2.has_value());
REQUIRE(c_res2.value() == 42);

#if TYPE_SAFE_USE_RETURN_TYPE_DEDUCTION
// just compiler check, see https://github.com/foonathan/type_safe/issues/60
struct bar
{
void non_const() {}
};

optional<bar> f = bar{};
f.map([](auto&& b) {
b.non_const();
return 42;
});
#endif
}
SECTION("with")
{
Expand Down

0 comments on commit 441f054

Please sign in to comment.