lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master e93e17f 3/4: Signed uniform container size


From: Greg Chicares
Subject: [lmi-commits] [lmi] master e93e17f 3/4: Signed uniform container size
Date: Mon, 4 Jun 2018 12:19:53 -0400 (EDT)

branch: master
commit e93e17f12769f763866e2d800566a4278aba41bb
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Signed uniform container size
    
    Naturally extend C++17 [iterator.container] (N4280) so that error-prone
    mixing of signed and unsigned can be avoided.
---
 Makefile.am        |   7 ++++
 objects.make       |   5 +++
 ssize_lmi.hpp      | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ssize_lmi_test.cpp |  59 +++++++++++++++++++++++++++++++
 4 files changed, 172 insertions(+)

diff --git a/Makefile.am b/Makefile.am
index 59d70c2..40a1d47 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -136,6 +136,7 @@ TESTS = \
     test_safely_dereference_as \
     test_sandbox \
     test_snprintf \
+    test_ssize_lmi \
     test_stratified_algorithms \
     test_stream_cast \
     test_system_command \
@@ -1032,6 +1033,11 @@ test_snprintf_SOURCES = \
   snprintf_test.cpp
 test_snprintf_CXXFLAGS = $(AM_CXXFLAGS)
 
+test_ssize_lmi_SOURCES = \
+  $(common_test_objects) \
+  ssize_lmi_test.cpp
+test_ssize_lmi_CXXFLAGS = $(AM_CXXFLAGS)
+
 test_stratified_algorithms_SOURCES = \
   $(common_test_objects) \
   stratified_algorithms_test.cpp
@@ -1285,6 +1291,7 @@ noinst_HEADERS = \
     single_choice_popup_menu.hpp \
     skeleton.hpp \
     so_attributes.hpp \
+    ssize_lmi.hpp \
     stl_extensions.hpp \
     stratified_algorithms.hpp \
     stratified_charges.hpp \
diff --git a/objects.make b/objects.make
index 853e71a..baec96a 100644
--- a/objects.make
+++ b/objects.make
@@ -459,6 +459,7 @@ unit_test_targets := \
   safely_dereference_as_test \
   sandbox_test \
   snprintf_test \
+  ssize_lmi_test \
   stratified_algorithms_test \
   stream_cast_test \
   system_command_test \
@@ -912,6 +913,10 @@ snprintf_test$(EXEEXT): \
   $(common_test_objects) \
   snprintf_test.o \
 
+ssize_lmi_test$(EXEEXT): \
+  $(common_test_objects) \
+  ssize_lmi_test.o \
+
 stratified_algorithms_test$(EXEEXT): \
   $(common_test_objects) \
   stratified_algorithms_test.o \
diff --git a/ssize_lmi.hpp b/ssize_lmi.hpp
new file mode 100644
index 0000000..db5c150
--- /dev/null
+++ b/ssize_lmi.hpp
@@ -0,0 +1,101 @@
+// Improved std::size() that returns a signed integer.
+//
+// Copyright (C) 2018 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#ifndef ssize_lmi_hpp
+#define ssize_lmi_hpp
+
+#include "config.hpp"
+
+#include "bourn_cast.hpp"
+
+#include <cstddef>                      // size_t
+#include <cstring>                      // strlen()
+#include <type_traits>                  // make_signed_t
+
+/// Motivation: to avoid error-prone mixing of signed and unsigned.
+///
+///   https://github.com/ericniebler/stl2/issues/182
+/// "The fact that .size() returns an unsigned integer and iterators'
+/// difference type is required to be signed pretty much guarantees
+/// that there will be signed/unsigned mismatches in simple and sane
+/// uses of the STL. It's a mess. We should use signed integers
+/// everywhere that bit-twiddling isn't required."
+///
+/// Also see:
+///   http://www.aristeia.com/Papers/C++ReportColumns/sep95.pdf
+/// and the panel discussion here:
+///   https://isocpp.org/blog/2013/09/goingnative-2013-videos-now-available
+/// relevant portions of which are transcribed below.
+///
+/// 12:55 Stroustrup: "Use int until you have a reason not to. Don't use
+/// unsigned unless you are fiddling with bit patterns. And never mix
+/// signed and unsigned."
+/// 42:55 Stroustrup: "Whenever you mix signed and unsigned numbers you
+/// get trouble. The rules are just very surprising, and they turn up in
+/// code in the strangest places. They correlate very strongly with bugs.
+/// Now, when people use unsigned numbers, they usually have a reason,
+/// and the reason will be something like, well, 'it can't be negative',
+/// or 'I need an extra bit'. If you need an extra bit, I am very
+/// reluctant to believe you that you really need it, and I don't think
+/// that's a good reason. When you think you can't have negative numbers,
+/// you will have somebody who initialized your unsigned with minus two,
+/// and think they get minus two--and things like that. It is just highly
+/// error prone. I think one of the sad things about the standard library
+/// is that the indices are unsigned, whereas array indices are signed,
+/// and you're sort of doomed to have confusion and problems with that.
+/// There are far too many integer types. There are far too lenient rules
+/// for mixing them together, and it's a major bug source--which is why
+/// I'm saying: stay as simple as you can, use integers till you really,
+/// really need something else."
+/// Sutter: "It's unfortunately a mistake in the STL, in the standard
+/// library, that we use unsigned indices."
+/// Carruth: "How frequently have you written arithmetic and wanted ...
+/// 2^32 modular behavior? That's really unusual. Why would you select a
+/// type which gives you that?"
+/// 1:02:50 Question: "but all of the ordinals in the STL, vector::size()
+/// and all that kind of stuff, they're unsigned and so it's..."
+/// Sutter: "They're wrong."
+/// Question: "...it's gonna pollute, right?"
+/// Sutter: "We're sorry. As Scott would say, 'we were young'."
+
+namespace lmi
+{
+using ssize_t = std::make_signed_t<std::size_t>;
+
+template<typename Container>
+constexpr ssize_t ssize(Container const& c)
+{
+    return bourn_cast<ssize_t>(c.size());
+}
+
+template<typename T, std::size_t n>
+constexpr ssize_t ssize(T const(&)[n])
+{
+    return bourn_cast<ssize_t>(n);
+}
+
+inline ssize_t sstrlen(char const* s)
+{
+    return bourn_cast<ssize_t>(std::strlen(s));
+}
+} // namespace lmi
+
+#endif // ssize_lmi_hpp
diff --git a/ssize_lmi_test.cpp b/ssize_lmi_test.cpp
new file mode 100644
index 0000000..c05f207
--- /dev/null
+++ b/ssize_lmi_test.cpp
@@ -0,0 +1,59 @@
+// Improved std::size() that returns a signed integer: unit test.
+//
+// Copyright (C) 2018 Gregory W. Chicares.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+//
+// http://savannah.nongnu.org/projects/lmi
+// email: <address@hidden>
+// snail: Chicares, 186 Belle Woods Drive, Glastonbury CT 06033, USA
+
+#include "pchfile.hpp"
+
+#include "ssize_lmi.hpp"
+
+#include "bourn_cast.hpp"
+#include "test_tools.hpp"
+
+#include <array>
+#include <cstring>                      // strlen()
+#include <iterator>                     // size()
+#include <string>
+#include <vector>
+
+int test_main(int, char*[])
+{
+    char const c[2] = {'0'};
+    BOOST_TEST_EQUAL(lmi::ssize(c), 2);
+    BOOST_TEST_EQUAL(lmi::ssize(c), bourn_cast<int>(std::size(c)));
+
+    std::array<int,3> const a{1, 2};
+    BOOST_TEST_EQUAL(lmi::ssize(a), 3);
+    BOOST_TEST_EQUAL(lmi::ssize(a), bourn_cast<int>(std::size(a)));
+
+    std::vector<int> const v(5);
+    BOOST_TEST_EQUAL(lmi::ssize(v), 5);
+    BOOST_TEST_EQUAL(lmi::ssize(v), bourn_cast<int>(std::size(v)));
+
+    std::string const s("abcdefg");
+    BOOST_TEST_EQUAL(lmi::ssize(s), 7);
+    BOOST_TEST_EQUAL(lmi::ssize(s), bourn_cast<int>(std::size(s)));
+
+    char const* p = "ABCDEFGHIJK";
+    BOOST_TEST_EQUAL(lmi::sstrlen(p), 11);
+    BOOST_TEST_EQUAL(lmi::sstrlen(p), bourn_cast<int>(std::strlen(p)));
+
+    return 0;
+}
+



reply via email to

[Prev in Thread] Current Thread [Next in Thread]