Skip to content

Commit

Permalink
Added template argument deduction for not_null (microsoft#689)
Browse files Browse the repository at this point in the history
* Added template  argument deduction for not_null

This allows compilers with c++17 support to infer template
instantiation types when calling not_null constructor:

    int foo(not_null<const int*> x);

    int main()
    {
        int t = 0;
        not_null x{ &t };
        return foo(not_null{ &t });
    }

* replaced deduction guides by a simple constructor

* Updated tests

* fixed check for availability of std::byte

* testing c++1z on clang

* fixed cmakelists extra endif

* include cstddef header for clang and gcc in pointers

* fixed a typo

* fix missing nullptr_t type

* fixed typo in CMakeLists.tst

* change approach to c++17 testing, step one: revert cmake testing, update clang5.0 package

removed using latest c++ due to clang5.0 failing,
update clang5.0 travis config to use llvm-toolchain-trusty-5.0

* addressed comments
  • Loading branch information
Anna Gringauze authored Jun 7, 2018
1 parent 75ad0c1 commit cb2d1af
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ matrix:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
- sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-4.0 main'
- sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'

- env: COMPILER=clang++-5.0 BUILD_TYPE=Release
Expand Down
17 changes: 14 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,31 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(GSL_STANDALONE_PROJECT ON)
endif ()


include(CheckCXXCompilerFlag)
if (NOT MSVC)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
else()
CHECK_CXX_COMPILER_FLAG("-std:c++14" COMPILER_SUPPORTS_CXX14)
endif()

# when minimum version required is 3.8.0 remove if below
# both branches do exactly the same thing
if (CMAKE_VERSION VERSION_LESS 3.7.9)
if (NOT MSVC)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
if(COMPILER_SUPPORTS_CXX14)
target_compile_options(GSL INTERFACE "-std=c++14")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
endif()
else()
if(COMPILER_SUPPORTS_CXX14)
target_compile_options(GSL INTERFACE "-std:c++14")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
endif()
endif()
else ()
# set the GSL library to be compiled only with c++14
target_compile_features(GSL INTERFACE cxx_std_14)
# on *nix systems force the use of -std=c++XX instead of -std=gnu++XX (default)
set(CMAKE_CXX_EXTENSIONS OFF)
Expand Down
6 changes: 6 additions & 0 deletions include/gsl/pointers
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ public:
Expects(ptr_ != nullptr);
}

template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
constexpr explicit not_null(T u) : ptr_(u)
{
Expects(ptr_ != nullptr);
}

template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
constexpr not_null(const not_null<U>& other) : not_null(other.get())
{
Expand Down
59 changes: 59 additions & 0 deletions tests/notnull_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct NonCopyableNonMovable
};

bool helper(not_null<int*> p) { return *p == 12; }
bool helper_const(not_null<const int*> p) { return *p == 12; }

TEST_CASE("TestNotNullConstructors")
{
Expand Down Expand Up @@ -328,4 +329,62 @@ TEST_CASE("TestNotNullCustomPtrComparison")
CHECK((NotNull2(p2) >= NotNull1(p1)) == (p2 >= p1));
}


#if defined(__cplusplus) && (__cplusplus >= 201703L)
TEST_CASE("TestNotNullConstructorTypeDeduction")
{
{
int i = 42;

not_null x{&i};
helper(not_null{&i});
helper_const(not_null{&i});

CHECK(*x == 42);
}

{
int i = 42;
int* p = &i;

not_null x{p};
helper(not_null{p});
helper_const(not_null{p});

CHECK(*x == 42);
}

{
auto workaround_macro = []() {
int* p1 = nullptr;
not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}

{
auto workaround_macro = []() {
const int* p1 = nullptr;
not_null x{p1};
};
CHECK_THROWS_AS(workaround_macro(), fail_fast);
}

{
int* p = nullptr;

CHECK_THROWS_AS(helper(not_null{p}), fail_fast);
CHECK_THROWS_AS(helper_const(not_null{p}), fail_fast);
}

#ifdef CONFIRM_COMPILATION_ERRORS
{
not_null x{nullptr};
helper(not_null{nullptr});
helper_const(not_null{nullptr});
}
#endif
}
#endif // #if defined(__cplusplus) && (__cplusplus >= 201703L)

static_assert(std::is_nothrow_move_constructible<not_null<void *>>::value, "not_null must be no-throw move constructible");

0 comments on commit cb2d1af

Please sign in to comment.