@@ -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}
824831constexpr 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
833840namespace 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- }
857842template <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
869890template <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}
875894template <class T , size_t N>
876895mutable_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}
882899template <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}
888903template <class T , size_t N>
889904const_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
897909template <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}
903913template <class T , size_t N>
904914mutable_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}
910918template <class T , size_t N>
911919const_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}
917923template <class T , size_t N>
918924const_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}
924928template <class T , size_t N>
925929const_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}
931933template <class T , size_t N>
932934const_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
939939template <class T , class Allocator >
940940mutable_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}
945944template <class T , class Allocator >
946945mutable_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}
951949template <class T , class Allocator >
952950const_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}
957954template <class T , class Allocator >
958955const_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
964960template <class T , class Traits , class Allocator >
965961mutable_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}
972965template <class T , class Traits , class Allocator >
973966mutable_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}
981971template <class T , class Traits , class Allocator >
982972const_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}
987976template <class T , class Traits , class Allocator >
988977const_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
997985template <class T , class Traits >
998986const_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}
1003990template <class T , class Traits >
1004991const_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