diff --git a/.travis.yml b/.travis.yml index 551b130..df3e6a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,23 @@ matrix: - env: BOGUS_JOB=true include: + - os: linux + compiler: g++ + env: TOOLSET=gcc COMPILER=g++ CXXSTD=11 + + - os: linux + compiler: g++-4.9 + env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=11 + addons: + apt: + packages: + - g++-4.9 + sources: + - ubuntu-toolchain-r-test + - os: linux compiler: g++-5 - env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=14,1z + env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=11,14,1z addons: apt: packages: @@ -36,7 +50,7 @@ matrix: - os: linux compiler: g++-6 - env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=14,1z + env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=11,14,1z addons: apt: packages: @@ -46,7 +60,7 @@ matrix: - os: linux compiler: g++-7 - env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=14,17 + env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=11,14,17 addons: apt: packages: @@ -56,7 +70,7 @@ matrix: - os: linux compiler: g++-8 - env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=14,17 + env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17 addons: apt: packages: @@ -66,7 +80,7 @@ matrix: - os: linux compiler: g++-8 - env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold + env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold addons: apt: packages: @@ -76,7 +90,7 @@ matrix: - os: linux compiler: clang++-3.5 - env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=11,14,1z addons: apt: packages: @@ -88,7 +102,7 @@ matrix: - os: linux compiler: clang++-3.6 - env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=11,14,1z addons: apt: packages: @@ -99,7 +113,7 @@ matrix: - os: linux compiler: clang++-3.7 - env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=11,14,1z addons: apt: packages: @@ -110,7 +124,7 @@ matrix: - os: linux compiler: clang++-3.8 - env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=11,14,1z addons: apt: packages: @@ -121,7 +135,7 @@ matrix: - os: linux compiler: clang++-3.9 - env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=11,14,1z addons: apt: packages: @@ -132,7 +146,7 @@ matrix: - os: linux compiler: clang++-4.0 - env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=11,14,1z addons: apt: packages: @@ -143,7 +157,7 @@ matrix: - os: linux compiler: clang++-5.0 - env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=11,14,1z addons: apt: packages: @@ -154,7 +168,7 @@ matrix: - os: linux compiler: clang++-6.0 - env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=14,17 + env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=11,14,17 addons: apt: packages: @@ -165,7 +179,7 @@ matrix: - os: linux compiler: clang++-6.0 - env: UBSAN=1 TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=14,1z UBSAN_OPTIONS=print_stacktrace=1 + env: UBSAN=1 TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1 addons: apt: packages: @@ -184,7 +198,7 @@ matrix: - os: linux compiler: clang++-libc++ - env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=14,1z UBSAN_OPTIONS=print_stacktrace=1 + env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1 addons: apt: packages: @@ -192,7 +206,7 @@ matrix: - os: osx compiler: clang++ - env: TOOLSET=clang COMPILER=clang++ CXXSTD=14,1z + env: TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z install: - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index a1ad459..fe0bfc7 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -1503,36 +1503,97 @@ template constexpr auto visit( F&& f, V1&& v1 ) -> variant2:: return mp_with_index>( v1.index(), detail::visit_L1{ std::forward(f), std::forward(v1) } ); } -#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) +#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) + +namespace detail +{ + +template struct bind_front_ +{ + F&& f; + A&& a; + + template auto operator()( T&&... t ) -> decltype( std::forward(f)( std::forward(a), std::forward(t)... ) ) + { + return std::forward(f)( std::forward(a), std::forward(t)... ); + } +}; + +template bind_front_ bind_front( F&& f, A&& a ) +{ + return bind_front_{ std::forward(f), std::forward(a) }; +} + +template struct visit_L2 +{ + F&& f; + + V1&& v1; + V2&& v2; + + template auto operator()( I ) const -> Vret + { + auto f2 = bind_front( std::forward(f), get( std::forward(v1) ) ); + return visit( f2, std::forward(v2) ); + } +}; + +} // namespace detail template constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> variant2::detail::Vret { - return mp_with_index>( v1.index(), [&]( auto I ){ - - auto f2 = [&]( auto&&... a ){ return std::forward(f)( get( std::forward(v1) ), std::forward(a)... ); }; - return visit( f2, std::forward(v2) ); - - }); + return mp_with_index>( v1.index(), detail::visit_L2{ std::forward(f), std::forward(v1), std::forward(v2) } ); } +namespace detail +{ + +template struct visit_L3 +{ + F&& f; + + V1&& v1; + V2&& v2; + V3&& v3; + + template auto operator()( I ) const -> Vret + { + auto f2 = bind_front( std::forward(f), get( std::forward(v1) ) ); + return visit( f2, std::forward(v2), std::forward(v3) ); + } +}; + +} // namespace detail + template constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> variant2::detail::Vret { - return mp_with_index>( v1.index(), [&]( auto I ){ - - auto f2 = [&]( auto&&... a ){ return std::forward(f)( get( std::forward(v1) ), std::forward(a)... ); }; - return visit( f2, std::forward(v2), std::forward(v3) ); - - }); + return mp_with_index>( v1.index(), detail::visit_L3{ std::forward(f), std::forward(v1), std::forward(v2), std::forward(v3) } ); } +namespace detail +{ + +template struct visit_L4 +{ + F&& f; + + V1&& v1; + V2&& v2; + V3&& v3; + V4&& v4; + + template auto operator()( I ) const -> Vret + { + auto f2 = bind_front( std::forward(f), get( std::forward(v1) ) ); + return visit( f2, std::forward(v2), std::forward(v3), std::forward(v4) ); + } +}; + +} // namespace detail + template constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> variant2::detail::Vret { - return mp_with_index>( v1.index(), [&]( auto I ){ - - auto f2 = [&]( auto&&... a ){ return std::forward(f)( get( std::forward(v1) ), std::forward(a)... ); }; - return visit( f2, std::forward(v2), std::forward(v3), std::forward(v4) ); - - }); + return mp_with_index>( v1.index(), detail::visit_L4{ std::forward(f), std::forward(v1), std::forward(v2), std::forward(v3), std::forward(v4) } ); } #else