From ec836c218f910a56f4249fe0ba689066db99981e Mon Sep 17 00:00:00 2001 From: Tom Scogland Date: Thu, 7 Nov 2019 10:38:05 +0000 Subject: [PATCH 01/19] concepts: refactor convertible_to out to is_convertible This is the beginning of a relatively large concepts/type-traits refactor that is going to come in over the next while. First is factoring out convertible_to so it looks/works more like the standard library version so I can start converting detector into a more user-friendly version we can actually expose. This is a bug for GEOSX and others, and should also make our type_traits more robust once it's all in. --- .gitignore | 3 ++ include/camp/defines.hpp | 3 ++ include/camp/detail/test.hpp | 21 ++++++++- include/camp/helpers.hpp | 51 ++++++++++++--------- include/camp/type_traits/is_convertible.hpp | 36 +++++++++++++++ test/CMakeLists.txt | 1 + test/convertible.cpp | 22 +++++++++ 7 files changed, 114 insertions(+), 23 deletions(-) create mode 100644 include/camp/type_traits/is_convertible.hpp create mode 100644 test/convertible.cpp diff --git a/.gitignore b/.gitignore index 4c82b137..63b6d750 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,8 @@ *.gch build/ build-*/ +cmake-build-* /Debug/ ./extern/googletest/* +.vscode +.idea diff --git a/include/camp/defines.hpp b/include/camp/defines.hpp index 3143209b..7ddcc4d6 100644 --- a/include/camp/defines.hpp +++ b/include/camp/defines.hpp @@ -88,6 +88,9 @@ using nullptr_t = decltype(nullptr); using type = typename X::type; \ } +#define CAMP_STRINGIFY_IMPL(x) #x +#define CAMP_STRINGIFY(x) CAMP_STRINGIFY_IMPL(x) +#define CAMP_UNQUOTE(...) __VA_ARGS__ } // namespace camp #endif diff --git a/include/camp/detail/test.hpp b/include/camp/detail/test.hpp index 3c5cbc78..3f96d51a 100644 --- a/include/camp/detail/test.hpp +++ b/include/camp/detail/test.hpp @@ -26,7 +26,6 @@ namespace test "is_same assertion failed "); static bool constexpr value = is_same::value; }; -#define CAMP_UNQUOTE(...) __VA_ARGS__ #define CAMP_CHECK_SAME(X, Y) \ static_assert( \ ::camp::test::AssertSame::value, \ @@ -45,6 +44,26 @@ namespace test static_assert( \ ::camp::test::AssertValue::value, \ #X "::value == " #Y) +template +struct AssertTrue { + static_assert(Assertion::value, + "value assertion failed "); + static bool const value = Assertion::value; +}; +#define CAMP_CHECK_VALUE(...) \ + static_assert( \ + ::camp::test::AssertTrue<__VA_ARGS__>::value, \ + "CAMP static assert failed, ::value is not true") +template +struct AssertFalse { + static_assert(!Assertion::value, + "value assertion failed "); + static bool const value = !Assertion::value; +}; +#define CAMP_CHECK_VALUE_NOT(...) \ + static_assert( \ + ::camp::test::AssertFalse<__VA_ARGS__>::value, \ + "CAMP static assert failed, ::value is true") } // namespace test #endif // CAMP_DOX ///\endcond diff --git a/include/camp/helpers.hpp b/include/camp/helpers.hpp index df355cb5..dec0f3b6 100644 --- a/include/camp/helpers.hpp +++ b/include/camp/helpers.hpp @@ -20,28 +20,6 @@ For details about use and distribution, please read LICENSE and NOTICE from namespace camp { -/// metafunction to get instance of pointer type -template -T* declptr(); - -/// metafunction to get instance of value type -template -auto val() noexcept -> decltype(std::declval()); - -/// metafunction to get instance of const type -template -auto cval() noexcept -> decltype(std::declval()); - -/// metafunction to expand a parameter pack and ignore result -template -CAMP_HOST_DEVICE void sink(Ts...) -{ -} - -// bring common utility routines into scope to allow ADL -using std::begin; -using std::swap; - namespace type { namespace ref @@ -144,6 +122,35 @@ namespace type } // namespace cv } // end namespace type +/// metafunction to get instance of pointer type +template +T* declptr(); + +/// metafunction to get instance of value type +template +type::rvref::add val() noexcept; +/// metafunction to get instance of value type +template +type::rvref::add declval() noexcept; + +/// metafunction to get instance of const type +template +auto cval() noexcept -> decltype(declval()); + +/// metafunction to expand a parameter pack and ignore result +template +CAMP_HOST_DEVICE void sink(Ts...) +{ +} + +/// metafunction to return a specific type if arg can be instantiated +template +Ret returns(T const&) noexcept; + +// bring common utility routines into scope to allow ADL +using std::begin; +using std::swap; + template using decay = type::cv::rem>; diff --git a/include/camp/type_traits/is_convertible.hpp b/include/camp/type_traits/is_convertible.hpp new file mode 100644 index 00000000..cb062f48 --- /dev/null +++ b/include/camp/type_traits/is_convertible.hpp @@ -0,0 +1,36 @@ +// +// Created by Tom Scogland on 11/5/19. +// + +#ifndef CAMP_IS_CONVERTIBLE_HPP +#define CAMP_IS_CONVERTIBLE_HPP + +#include "../number/number.hpp" +#include "../helpers.hpp" + +namespace camp +{ + +namespace detail +{ + template + constexpr void test_conversion(T &&u) noexcept; +} + +/// type trait to validate T is convertible to U +template +struct is_convertible : false_type { +}; + +/// type trait to validate T is convertible to U +template +struct is_convertible(val()))> : true_type { +}; + +/// type trait to validate T is convertible to U +template +using is_convertible_t = typename is_convertible::type; + +} // namespace camp + +#endif // CAMP_IS_CONVERTIBLE_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4973ee9a..eb57846c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -117,6 +117,7 @@ camp_add_test(tuple_out_of_range RUN) camp_add_test(accumulate) camp_add_test(at_key) +camp_add_test(convertible) camp_add_test(filter) camp_add_test(find_if) camp_add_test(flatten) diff --git a/test/convertible.cpp b/test/convertible.cpp new file mode 100644 index 00000000..7d24db0e --- /dev/null +++ b/test/convertible.cpp @@ -0,0 +1,22 @@ +// +// Created by Tom Scogland on 11/5/19. +// + +#include +#include + +using namespace camp; + +class A {}; +class B : public A {}; +class C {}; +class D { public: operator C() { return c; } C c; }; + + +CAMP_CHECK_VALUE(is_convertible); +CAMP_CHECK_VALUE_NOT(is_convertible); +CAMP_CHECK_VALUE_NOT(is_convertible); +CAMP_CHECK_VALUE(is_convertible_t); + +CAMP_CHECK_VALUE(is_convertible); +CAMP_CHECK_VALUE(is_convertible); From d2b86c774db1a287610378f5507691c170315e2f Mon Sep 17 00:00:00 2001 From: Tom Scogland Date: Thu, 7 Nov 2019 11:11:35 +0000 Subject: [PATCH 02/19] concepts: refactor detection out into detect.hpp With the is_convertible changes, this is the basis for the whole refactor setup. Concepts will all be defined against the new detector, as will type traits, using the new idiom through the macro so if we need to do this again it wont have to touch them all. --- include/camp/concepts/detect.hpp | 94 ++++++++++++++ include/camp/type_traits/is_convertible.hpp | 9 +- test/CMakeLists.txt | 1 + test/detect.cpp | 135 ++++++++++++++++++++ 4 files changed, 235 insertions(+), 4 deletions(-) create mode 100644 include/camp/concepts/detect.hpp create mode 100644 test/detect.cpp diff --git a/include/camp/concepts/detect.hpp b/include/camp/concepts/detect.hpp new file mode 100644 index 00000000..7fdec664 --- /dev/null +++ b/include/camp/concepts/detect.hpp @@ -0,0 +1,94 @@ +// +// Created by Tom Scogland on 11/5/19. +// + +#ifndef CAMP_DETECT_HPP +#define CAMP_DETECT_HPP + +#include "../number/number.hpp" +#include "../type_traits/is_convertible.hpp" +#include "../type_traits/is_same.hpp" + +namespace camp +{ + +namespace detail +{ + template + struct void_t { + using type = void; + }; + + struct nonesuch { + + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const &) = delete; + void operator=(nonesuch const &) = delete; + }; + + template + class Concept, + class... Args> + struct _detector { + using value_t = ::camp::false_type; + constexpr static auto value = false; + using type = Default; + }; + + template class Concept, class... Args> + struct _detector>::type, + Concept, + Args...> { + using value_t = ::camp::true_type; + constexpr static auto value = true; + // using type = typename Concept::type; + using type = Concept; + }; + + template + camp::true_type ___valid_expr___(T &&...) noexcept; +} // namespace detail + +template