Skip to content

Commit bbba565

Browse files
committed
Simplify implementation of buffer creation functions
1 parent 809acb2 commit bbba565

File tree

1 file changed

+66
-80
lines changed

1 file changed

+66
-80
lines changed

zmq.hpp

Lines changed: 66 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,9 @@ class mutable_buffer
737737
constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {}
738738
constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n)
739739
{
740+
#ifdef ZMQ_CPP14
740741
assert(p != nullptr || n == 0);
742+
#endif
741743
}
742744

743745
constexpr void *data() const noexcept { return _data; }
@@ -770,7 +772,12 @@ class const_buffer
770772
{
771773
public:
772774
constexpr const_buffer() noexcept : _data(nullptr), _size(0) {}
773-
constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n) {}
775+
constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n)
776+
{
777+
#ifdef ZMQ_CPP14
778+
assert(p != nullptr || n == 0);
779+
#endif
780+
}
774781
constexpr const_buffer(const mutable_buffer &mb) noexcept :
775782
_data(mb.data()),
776783
_size(mb.size())
@@ -817,43 +824,21 @@ constexpr mutable_buffer buffer(const mutable_buffer& mb) noexcept
817824
{
818825
return mb;
819826
}
820-
constexpr mutable_buffer buffer(const mutable_buffer& mb, size_t n) noexcept
827+
inline mutable_buffer buffer(const mutable_buffer& mb, size_t n) noexcept
821828
{
822829
return mutable_buffer(mb.data(), (std::min)(mb.size(), n));
823830
}
824831
constexpr const_buffer buffer(const const_buffer& cb) noexcept
825832
{
826833
return cb;
827834
}
828-
constexpr const_buffer buffer(const const_buffer& cb, size_t n) noexcept
835+
inline const_buffer buffer(const const_buffer& cb, size_t n) noexcept
829836
{
830837
return const_buffer(cb.data(), (std::min)(cb.size(), n));
831838
}
832839

833840
namespace detail
834841
{
835-
// utility functions for containers with data and size
836-
// data is nullptr if the container is empty
837-
template<class T> mutable_buffer buffar_mut_ds(T &data) noexcept
838-
{
839-
return mutable_buffer(data.size() != 0u ? data.data() : nullptr,
840-
data.size() * sizeof(*data.data()));
841-
}
842-
template<class T> mutable_buffer buffar_mut_ds(T &data, size_t n_bytes) noexcept
843-
{
844-
return mutable_buffer(data.size() != 0u ? data.data() : nullptr,
845-
(std::min)(data.size() * sizeof(*data.data()), n_bytes));
846-
}
847-
template<class T> const_buffer buffar_const_ds(const T &data) noexcept
848-
{
849-
return const_buffer(data.size() != 0u ? data.data() : nullptr,
850-
data.size() * sizeof(*data.data()));
851-
}
852-
template<class T> const_buffer buffar_const_ds(const T &data, size_t n_bytes) noexcept
853-
{
854-
return const_buffer(data.size() != 0u ? data.data() : nullptr,
855-
(std::min)(data.size() * sizeof(*data.data()), n_bytes));
856-
}
857842
template<class T> struct is_pod_like
858843
{
859844
// NOTE: The networking draft N4771 section 16.11 requires
@@ -863,148 +848,149 @@ template<class T> struct is_pod_like
863848
static constexpr bool value =
864849
std::is_trivially_copyable<T>::value && std::is_standard_layout<T>::value;
865850
};
851+
852+
template<class C> constexpr auto seq_size(const C &c) noexcept -> decltype(c.size())
853+
{
854+
return c.size();
855+
}
856+
template<class T, size_t N>
857+
constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept
858+
{
859+
return N;
860+
}
861+
862+
template<class Seq>
863+
auto buffer_contiguous_sequence(Seq &&seq) noexcept
864+
-> decltype(buffer(std::addressof(*std::begin(seq)), size_t{}))
865+
{
866+
using T = typename std::remove_cv<
867+
typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
868+
static_assert(detail::is_pod_like<T>::value, "T must be POD");
869+
870+
const auto size = seq_size(seq);
871+
return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
872+
size * sizeof(T));
873+
}
874+
template<class Seq>
875+
auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept
876+
-> decltype(buffer_contiguous_sequence(seq))
877+
{
878+
using T = typename std::remove_cv<
879+
typename std::remove_reference<decltype(*std::begin(seq))>::type>::type;
880+
static_assert(detail::is_pod_like<T>::value, "T must be POD");
881+
882+
const auto size = seq_size(seq);
883+
return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr,
884+
(std::min)(size * sizeof(T), n_bytes));
885+
}
886+
866887
} // namespace detail
867888

868889
// C array
869890
template<class T, size_t N> mutable_buffer buffer(T (&data)[N]) noexcept
870891
{
871-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
872-
static_assert(N > 0, "N > 0");
873-
return mutable_buffer(static_cast<T *>(data), N * sizeof(T));
892+
return detail::buffer_contiguous_sequence(data);
874893
}
875894
template<class T, size_t N>
876895
mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept
877896
{
878-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
879-
static_assert(N > 0, "N > 0");
880-
return mutable_buffer(static_cast<T *>(data), (std::min)(N * sizeof(T), n_bytes));
897+
return detail::buffer_contiguous_sequence(data, n_bytes);
881898
}
882899
template<class T, size_t N> const_buffer buffer(const T (&data)[N]) noexcept
883900
{
884-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
885-
static_assert(N > 0, "N > 0");
886-
return const_buffer(static_cast<const T *>(data), N * sizeof(T));
901+
return detail::buffer_contiguous_sequence(data);
887902
}
888903
template<class T, size_t N>
889904
const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept
890905
{
891-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
892-
static_assert(N > 0, "N > 0");
893-
return const_buffer(static_cast<const T *>(data),
894-
(std::min)(N * sizeof(T), n_bytes));
906+
return detail::buffer_contiguous_sequence(data, n_bytes);
895907
}
896908
// std::array
897909
template<class T, size_t N> mutable_buffer buffer(std::array<T, N> &data) noexcept
898910
{
899-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
900-
static_assert(N > 0, "N > 0");
901-
return mutable_buffer(data.data(), N * sizeof(T));
911+
return detail::buffer_contiguous_sequence(data);
902912
}
903913
template<class T, size_t N>
904914
mutable_buffer buffer(std::array<T, N> &data, size_t n_bytes) noexcept
905915
{
906-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
907-
static_assert(N > 0, "N > 0");
908-
return mutable_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
916+
return detail::buffer_contiguous_sequence(data, n_bytes);
909917
}
910918
template<class T, size_t N>
911919
const_buffer buffer(std::array<const T, N> &data) noexcept
912920
{
913-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
914-
static_assert(N > 0, "N > 0");
915-
return const_buffer(data.data(), N * sizeof(T));
921+
return detail::buffer_contiguous_sequence(data);
916922
}
917923
template<class T, size_t N>
918924
const_buffer buffer(std::array<const T, N> &data, size_t n_bytes) noexcept
919925
{
920-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
921-
static_assert(N > 0, "N > 0");
922-
return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
926+
return detail::buffer_contiguous_sequence(data, n_bytes);
923927
}
924928
template<class T, size_t N>
925929
const_buffer buffer(const std::array<T, N> &data) noexcept
926930
{
927-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
928-
static_assert(N > 0, "N > 0");
929-
return const_buffer(data.data(), N * sizeof(T));
931+
return detail::buffer_contiguous_sequence(data);
930932
}
931933
template<class T, size_t N>
932934
const_buffer buffer(const std::array<T, N> &data, size_t n_bytes) noexcept
933935
{
934-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
935-
static_assert(N > 0, "N > 0");
936-
return const_buffer(data.data(), (std::min)(N * sizeof(T), n_bytes));
936+
return detail::buffer_contiguous_sequence(data, n_bytes);
937937
}
938938
// std::vector
939939
template<class T, class Allocator>
940940
mutable_buffer buffer(std::vector<T, Allocator> &data) noexcept
941941
{
942-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
943-
return detail::buffar_mut_ds(data);
942+
return detail::buffer_contiguous_sequence(data);
944943
}
945944
template<class T, class Allocator>
946945
mutable_buffer buffer(std::vector<T, Allocator> &data, size_t n_bytes) noexcept
947946
{
948-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
949-
return detail::buffar_mut_ds(data, n_bytes);
947+
return detail::buffer_contiguous_sequence(data, n_bytes);
950948
}
951949
template<class T, class Allocator>
952950
const_buffer buffer(const std::vector<T, Allocator> &data) noexcept
953951
{
954-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
955-
return detail::buffar_const_ds(data);
952+
return detail::buffer_contiguous_sequence(data);
956953
}
957954
template<class T, class Allocator>
958955
const_buffer buffer(const std::vector<T, Allocator> &data, size_t n_bytes) noexcept
959956
{
960-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
961-
return detail::buffar_const_ds(data, n_bytes);
957+
return detail::buffer_contiguous_sequence(data, n_bytes);
962958
}
963959
// std::basic_string
964960
template<class T, class Traits, class Allocator>
965961
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data) noexcept
966962
{
967-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
968-
// before C++17 string::data() returned const char*
969-
return mutable_buffer(data.size() != 0u ? &data[0] : nullptr,
970-
data.size() * sizeof(T));
963+
return detail::buffer_contiguous_sequence(data);
971964
}
972965
template<class T, class Traits, class Allocator>
973966
mutable_buffer buffer(std::basic_string<T, Traits, Allocator> &data,
974967
size_t n_bytes) noexcept
975968
{
976-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
977-
// before C++17 string::data() returned const char*
978-
return mutable_buffer(data.size() != 0u ? &data[0] : nullptr,
979-
(std::min)(data.size() * sizeof(T), n_bytes));
969+
return detail::buffer_contiguous_sequence(data, n_bytes);
980970
}
981971
template<class T, class Traits, class Allocator>
982972
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data) noexcept
983973
{
984-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
985-
return detail::buffar_const_ds(data);
974+
return detail::buffer_contiguous_sequence(data);
986975
}
987976
template<class T, class Traits, class Allocator>
988977
const_buffer buffer(const std::basic_string<T, Traits, Allocator> &data,
989978
size_t n_bytes) noexcept
990979
{
991-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
992-
return detail::buffar_const_ds(data, n_bytes);
980+
return detail::buffer_contiguous_sequence(data, n_bytes);
993981
}
994982

995983
#ifdef ZMQ_CPP17
996984
// std::basic_string_view
997985
template<class T, class Traits>
998986
const_buffer buffer(std::basic_string_view<T, Traits> data) noexcept
999987
{
1000-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
1001-
return detail::buffar_const_ds(data);
988+
return detail::buffer_contiguous_sequence(data);
1002989
}
1003990
template<class T, class Traits>
1004991
const_buffer buffer(std::basic_string_view<T, Traits> data, size_t n_bytes) noexcept
1005992
{
1006-
static_assert(detail::is_pod_like<T>::value, "T must be POD");
1007-
return detail::buffar_const_ds(data, n_bytes);
993+
return detail::buffer_contiguous_sequence(data, n_bytes);
1008994
}
1009995
#endif
1010996

0 commit comments

Comments
 (0)