diff --git a/.appveyor.yml b/.appveyor.yml index 836d15f..a63e496 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,11 +1,21 @@ os: -- Visual Studio 2015 -- Visual Studio 2017 + - Visual Studio 2017 + - Visual Studio 2015 + +environment: + matrix: + - STD: 17 + - STD: 14 build_script: - git submodule update --init --recursive - mkdir build - cd build - - cmake .. + - cmake -DCMAKE_CXX_STANDARD=%STD% -DCMAKE_CXX_STANDARD_REQUIRED=True .. - cmake --build . - C:\projects\function-ref\build\Debug\tests.exe + +matrix: + exclude: + - os: Visual Studio 2015 + STD: 17 diff --git a/.travis.yml b/.travis.yml index a541aaf..7ee82a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,14 @@ sudo: false matrix: include: + - compiler: gcc + addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-7 + env: COMPILER=g++-7 CXX_STANDARD=17 - compiler: gcc addons: apt: diff --git a/CMakeLists.txt b/CMakeLists.txt index aa4cc31..8829e22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,40 +1,50 @@ -cmake_minimum_required(VERSION 3.11) - -project(tl-function_ref VERSION 1.0.0 LANGUAGES CXX) - -option(FUNCTION_REF_ENABLE_TESTS "Enable tests." ON) - -include(FetchContent) +cmake_minimum_required(VERSION 3.11) + +project(tl-function_ref VERSION 1.0.0 LANGUAGES CXX) + +option(FUNCTION_REF_ENABLE_TESTS "Enable tests." ON) + +include(FetchContent) FetchContent_Declare( tl_cmake - GIT_REPOSITORY https://github.com/TartanLlama/tl-cmake.git -) + GIT_REPOSITORY https://github.com/burnpanck/tl-cmake.git + GIT_TAG b6fe9104d205cf04c4aac3824c2d310959b66120 +) FetchContent_GetProperties(tl_cmake) if(NOT tl_cmake_POPULATED) FetchContent_Populate(tl_cmake) set(CMAKE_MODULE_PATH ${tl_cmake_SOURCE_DIR} ${CMAKE_MODULE_PATH}) -endif() -include(add-tl) - -tl_add_library(function-ref SOURCES - include/tl/function_ref.hpp) - -# Prepare "Catch" library for other executables -set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) -add_library(Catch INTERFACE) -target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) - -if(FUNCTION_REF_ENABLE_TESTS) - # Make test executable - set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tests/call.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tests/issues.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp) - - add_executable(tests ${TEST_SOURCES}) - - target_link_libraries(tests Catch function-ref) - - set_property(TARGET tests PROPERTY CXX_STANDARD 14) -endif() \ No newline at end of file +endif() +include(add-tl) + +tl_add_library(function-ref ARCH_INDEPENDENT SOURCES + include/tl/function_ref.hpp) + +# make sure we see the C++ version, even in MSVC: +# https://stackoverflow.com/questions/57102212/cannot-set-cplusplus-to-c17-standard-with-visual-studio-and-cmake +if ((MSVC) AND (MSVC_VERSION GREATER_EQUAL 1914)) + target_compile_options(function-ref INTERFACE "/Zc:__cplusplus") +endif() + +# Prepare "Catch" library for other executables +set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/test) +add_library(Catch INTERFACE) +target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) + +if(FUNCTION_REF_ENABLE_TESTS) + # Make test executable + set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tests/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests/constructors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests/call.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests/issues.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tests/assignment.cpp) + + add_executable(tests ${TEST_SOURCES}) + + target_link_libraries(tests Catch function-ref) + + message(STATUS "CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}") + if(NOT CMAKE_CXX_STANDARD) + set_property(TARGET tests PROPERTY CXX_STANDARD 14) + endif() +endif() diff --git a/include/tl/function_ref.hpp b/include/tl/function_ref.hpp index 4b90dbf..3a47291 100644 --- a/include/tl/function_ref.hpp +++ b/include/tl/function_ref.hpp @@ -109,12 +109,20 @@ using invoke_result = invoke_result_impl; template using invoke_result_t = typename invoke_result::type; +#if __cplusplus >= 201703 +template +using is_prvalue_convertible = std::bool_constant || std::is_convertible_v>; +#else +template +using is_prvalue_convertible = std::is_convertible; +#endif + template struct is_invocable_r_impl : std::false_type {}; template struct is_invocable_r_impl< - typename std::is_convertible, R>::type, R, F, Args...> + typename is_prvalue_convertible, R>::type, R, F, Args...> : std::true_type {}; template diff --git a/tests/issues.cpp b/tests/issues.cpp index df40c1d..a146015 100644 --- a/tests/issues.cpp +++ b/tests/issues.cpp @@ -29,4 +29,20 @@ TEST_CASE("Issue #10") { int z = 12; auto f = [&](const std::vector i) { return i[0] * z; }; foo(f); -} \ No newline at end of file +} + +#if __cplusplus >= 201703 +struct NonCopyNonMove { + NonCopyNonMove() = default; + NonCopyNonMove(const NonCopyNonMove &) = delete; + NonCopyNonMove(NonCopyNonMove &&) = delete; +}; + +TEST_CASE("Issue #20") { + auto f = []() { return NonCopyNonMove(); }; + auto fr = tl::function_ref(f); + + // silence warnings + (void)fr; +} +#endif