[PATCH] Finish implementing P0426R1 "Constexpr for std::char_traits" for C++17

Pedro Alves palves@redhat.com
Mon Jun 12 22:28:00 GMT 2017


On 06/05/2017 03:27 PM, Jonathan Wakely wrote:

> Pedro, this is OK for trunk now we're in stage 1. Please go ahead and
> commit it - thanks.

Thanks Jonathan.  I've pushed it in now.

> 
> It's probably safe for gcc-7-branch too, but let's leave it on trunk
> for a while first.

OK.

BTW, for extra thoroughness, to confirm we're handling both
const & non-const arrays correctly, I had written this testsuite
tweak too.  Would you like to have this in?

>From 3f7adab8bab68955aafd760467bb860057140d40 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Mon, 12 Jun 2017 20:23:23 +0100
Subject: [PATCH] constexpr char_traits: Test non-const strings/arrays too

libstdc++-v3/ChangeLog
yyyy-mm-dd  Pedro Alves  <palves@redhat.com>

	* testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc
	(test_assign, test_compare, test_length, test_find): Test
	non-const strings/arrays too.
	(struct C): Add a generic conversion ctor.
---
 .../requirements/constexpr_functions_c++17.cc      | 173 ++++++++++++++++++---
 1 file changed, 150 insertions(+), 23 deletions(-)

diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc
index efd280f..c41b490 100644
--- a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc
+++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++17.cc
@@ -25,10 +25,40 @@ template<typename CT>
   test_assign()
   {
     using char_type = typename CT::char_type;
-    char_type s1[2] = {};
-    const char_type s2[2] = {1, 0};
-    CT::assign(s1[0], s2[0]);
-    return s1[0] == char_type{1};
+
+    auto check = [](char_type* s1, const char_type* s2)
+      {
+	CT::assign(s1[0], s2[0]);
+	return s1[0] == char_type{1};
+      };
+
+    // const strings.
+
+    {
+      char_type s1[2] = {};
+      const char_type s2[2] = {1, 0};
+      if (!check (s1, s2))
+	return false;
+    }
+
+    // non-const strings.
+
+    {
+      char_type s1[2] = {};
+      char_type s2[2] = {1, 0};
+      if (!check (s1, s2))
+	return false;
+    }
+
+    {
+      char_type s1[2] = {};
+      char_type s2[2] = {};
+      s2[0] = char_type{1};
+      if (!check (s1, s2))
+	return false;
+    }
+
+    return true;
   }
 
 template<typename CT>
@@ -36,14 +66,48 @@ template<typename CT>
   test_compare()
   {
     using char_type = typename CT::char_type;
-    const char_type s1[3] = {1, 2, 3};
-    const char_type s2[3] = {1, 2, 3};
-    if (CT::compare(s1, s2, 3) != 0)
-      return false;
-    if (CT::compare(s2, s1, 3) != 0)
-      return false;
-    if (CT::compare(s1+1, s2, 2) <= 0)
-      return false;
+
+    auto check = [](const char_type* s1, const char_type* s2)
+      {
+	if (CT::compare(s1, s2, 3) != 0)
+	  return false;
+	if (CT::compare(s2, s1, 3) != 0)
+	  return false;
+	if (CT::compare(s1+1, s2, 2) <= 0)
+	  return false;
+	return true;
+      };
+
+    // const arrays.
+
+    {
+      const char_type s1[3] = {1, 2, 3};
+      const char_type s2[3] = {1, 2, 3};
+      if (!check (s1, s2))
+	return false;
+    }
+
+    // non-const arrays.
+
+    {
+      char_type s1[3] = {1, 2, 3};
+      char_type s2[3] = {1, 2, 3};
+      if (!check (s1, s2))
+	return false;
+    }
+
+    {
+      char_type s1[3] = {};
+      char_type s2[3] = {};
+      for (size_t i = 0; i < 3; i++)
+	{
+	  s1[i] = char_type(i+1);
+	  s2[i] = char_type(i+1);
+	}
+      if (!check (s1, s2))
+	return false;
+    }
+
     return true;
   }
 
@@ -52,11 +116,40 @@ template<typename CT>
   test_length()
   {
     using char_type = typename CT::char_type;
-    const char_type s1[4] = {1, 2, 3, 0};
-    if (CT::length(s1) != 3)
-      return false;
-    if (CT::length(s1+1) != 2)
-      return false;
+
+    auto check = [](const char_type* s)
+      {
+	if (CT::length(s) != 3)
+	  return false;
+	if (CT::length(s+1) != 2)
+	  return false;
+	return true;
+      };
+
+    // const strings.
+
+    {
+      const char_type s[4] = {1, 2, 3, 0};
+      if (!check (s))
+	return false;
+    }
+
+    // non-const strings.
+
+    {
+      char_type s[4] = {1, 2, 3, 0};
+      if (!check (s))
+	return false;
+    }
+
+    {
+      char_type s[4] = {};
+      for (size_t i = 0; i < 3; i++)
+	s[i] = char_type(i+1);
+      if (!check (s))
+	return false;
+    }
+
     return true;
   }
 
@@ -65,11 +158,40 @@ template<typename CT>
   test_find()
   {
     using char_type = typename CT::char_type;
-    const char_type s1[3] = {1, 2, 3};
-    if (CT::find(s1, 3, char_type{2}) != s1+1)
-      return false;
-    if (CT::find(s1, 3, char_type{4}) != nullptr)
-      return false;
+
+    auto check = [](const char_type* s)
+      {
+	if (CT::find(s, 3, char_type{2}) != s+1)
+	  return false;
+	if (CT::find(s, 3, char_type{4}) != nullptr)
+	  return false;
+	return true;
+      };
+
+    // const arrays.
+
+    {
+      const char_type s[3] = {1, 2, 3};
+      if (!check(s))
+	return false;
+    }
+
+    // non-const arrays.
+
+    {
+      char_type s[3] = {1, 2, 3};
+      if (!check(s))
+	return false;
+    }
+
+    {
+      char_type s[3] = {};
+      for (size_t i = 0; i < 3; i++)
+	s[i] = char_type(i+1);
+      if (!check(s))
+	return false;
+    }
+
     return true;
   }
 
@@ -98,7 +220,12 @@ static_assert( test_compare<std::char_traits<char32_t>>() );
 static_assert( test_length<std::char_traits<char32_t>>() );
 static_assert( test_find<std::char_traits<char32_t>>() );
 
-struct C { unsigned char c; };
+struct C
+{
+  C() = default;
+  constexpr C(auto c_) : c(c_) {}
+  unsigned char c;
+};
 constexpr bool operator==(const C& c1, const C& c2) { return c1.c == c2.c; }
 constexpr bool operator<(const C& c1, const C& c2) { return c1.c < c2.c; }
 static_assert( test_assign<std::char_traits<C>>() );
-- 
2.5.5




More information about the Gcc-patches mailing list