diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 59c20a9..5c91ac4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -25,7 +25,8 @@ add_executable( poller.cpp active_poller.cpp multipart.cpp - monitor.cpp + monitor.cpp + utilities.cpp ) add_dependencies(unit_tests catch) diff --git a/tests/message.cpp b/tests/message.cpp index e2cc510..d872107 100644 --- a/tests/message.cpp +++ b/tests/message.cpp @@ -13,17 +13,6 @@ static_assert(std::is_nothrow_swappable::value, "message_t should be nothrow swappable"); #endif -#ifdef ZMQ_CPP11 -TEST_CASE("range SFINAE", "[message]") -{ - CHECK(!zmq::detail::is_range::value); - CHECK(zmq::detail::is_range::value); - CHECK(zmq::detail::is_range::value); - CHECK(zmq::detail::is_range::value); - CHECK(zmq::detail::is_range::value); -} -#endif - TEST_CASE("message default constructed", "[message]") { const zmq::message_t message; diff --git a/tests/utilities.cpp b/tests/utilities.cpp new file mode 100644 index 0000000..c7b8c99 --- /dev/null +++ b/tests/utilities.cpp @@ -0,0 +1,96 @@ +#include +#include + +#ifdef ZMQ_CPP11 + +namespace test_ns +{ +struct T_nr +{ +}; +struct T_mr +{ + void *begin() const noexcept { return nullptr; } + void *end() const noexcept { return nullptr; } +}; +struct T_fr +{ +}; +void *begin(const T_fr &) noexcept +{ + return nullptr; +} +void *end(const T_fr &) noexcept +{ + return nullptr; +} +struct T_mfr +{ + void *begin() const noexcept { return nullptr; } + void *end() const noexcept { return nullptr; } +}; +void *begin(const T_mfr &) noexcept +{ + return nullptr; +} +void *end(const T_mfr &) noexcept +{ + return nullptr; +} + +// types with associated namespace std +struct T_assoc_ns_nr : std::exception +{ +}; +struct T_assoc_ns_mr : std::exception +{ + void *begin() const noexcept { return nullptr; } + void *end() const noexcept { return nullptr; } +}; +struct T_assoc_ns_fr : std::exception +{ +}; +void *begin(const T_assoc_ns_fr &) noexcept +{ + return nullptr; +} +void *end(const T_assoc_ns_fr &) noexcept +{ + return nullptr; +} +struct T_assoc_ns_mfr : std::exception +{ + void *begin() const noexcept { return nullptr; } + void *end() const noexcept { return nullptr; } +}; +void *begin(const T_assoc_ns_mfr &) noexcept +{ + return nullptr; +} +void *end(const T_assoc_ns_mfr &) noexcept +{ + return nullptr; +} +} // namespace test_ns + +TEST_CASE("range SFINAE", "[utilities]") +{ + CHECK(!zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range>::value); + + CHECK(!zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + + CHECK(!zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); + CHECK(zmq::detail::is_range::value); +} + +#endif diff --git a/zmq.hpp b/zmq.hpp index 4cd3cc8..8d58cdb 100644 --- a/zmq.hpp +++ b/zmq.hpp @@ -156,6 +156,22 @@ namespace zmq #ifdef ZMQ_CPP11 namespace detail { +namespace ranges +{ +using std::begin; +using std::end; +template +auto begin(T&& r) -> decltype(begin(std::forward(r))) +{ + return begin(std::forward(r)); +} +template +auto end(T&& r) -> decltype(end(std::forward(r))) +{ + return end(std::forward(r)); +} +} // namespace ranges + template using void_t = void; template @@ -163,7 +179,7 @@ using iter_value_t = typename std::iterator_traits::value_type; template using range_iter_t = decltype( - std::begin(std::declval::type &>())); + ranges::begin(std::declval::type &>())); template using range_value_t = iter_value_t>; @@ -176,8 +192,8 @@ template struct is_range< T, void_t::type &>()) - == std::end(std::declval::type &>()))>> + ranges::begin(std::declval::type &>()) + == ranges::end(std::declval::type &>()))>> : std::true_type { }; @@ -316,7 +332,8 @@ class message_t detail::is_range::value && std::is_trivially_copyable>::value && !std::is_same::value>::type> - explicit message_t(const Range &rng) : message_t(std::begin(rng), std::end(rng)) + explicit message_t(const Range &rng) : + message_t(detail::ranges::begin(rng), detail::ranges::end(rng)) { } #endif