Przeglądaj źródła

Endian: constexpr constructors and conversion operators

Problem:
- Constructors and conversion operators are not `constexpr`,
  but they can be.
- `constexpr` is needed here so that other classes can add `constexpr`
  evaluation.

Solution:
- Add the `constexpr` keyword to the constructors and
  conversion operators.
- Add `static_assert` tests which ensure the capability works.
Lenny Maiorani 4 lat temu
rodzic
commit
151b8b5984
2 zmienionych plików z 47 dodań i 8 usunięć
  1. 8 8
      AK/Endian.h
  2. 39 0
      AK/Tests/TestEndian.cpp

+ 8 - 8
AK/Endian.h

@@ -32,7 +32,7 @@
 namespace AK {
 
 template<typename T>
-ALWAYS_INLINE T convert_between_host_and_little_endian(T value)
+ALWAYS_INLINE constexpr T convert_between_host_and_little_endian(T value)
 {
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     return value;
@@ -49,7 +49,7 @@ ALWAYS_INLINE T convert_between_host_and_little_endian(T value)
 }
 
 template<typename T>
-ALWAYS_INLINE T convert_between_host_and_big_endian(T value)
+ALWAYS_INLINE constexpr T convert_between_host_and_big_endian(T value)
 {
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     if constexpr (sizeof(T) == 8)
@@ -87,14 +87,14 @@ public:
     friend InputStream& operator>><T>(InputStream&, LittleEndian<T>&);
     friend OutputStream& operator<<<T>(OutputStream&, LittleEndian<T>);
 
-    LittleEndian() { }
+    constexpr LittleEndian() { }
 
-    LittleEndian(T value)
+    constexpr LittleEndian(T value)
         : m_value(convert_between_host_and_little_endian(value))
     {
     }
 
-    operator T() const { return convert_between_host_and_little_endian(m_value); }
+    constexpr operator T() const { return convert_between_host_and_little_endian(m_value); }
 
 private:
     T m_value { 0 };
@@ -116,14 +116,14 @@ public:
     friend InputStream& operator>><T>(InputStream&, BigEndian<T>&);
     friend OutputStream& operator<<<T>(OutputStream&, BigEndian<T>);
 
-    BigEndian() { }
+    constexpr BigEndian() = default;
 
-    BigEndian(T value)
+    constexpr BigEndian(T value)
         : m_value(convert_between_host_and_big_endian(value))
     {
     }
 
-    operator T() const { return convert_between_host_and_big_endian(m_value); }
+    constexpr operator T() const { return convert_between_host_and_big_endian(m_value); }
 
 private:
     T m_value { 0 };

+ 39 - 0
AK/Tests/TestEndian.cpp

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020, the SerenityOS developers.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ *    list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/TestSuite.h>
+
+#include <AK/Endian.h>
+
+static_assert(BigEndian<u32> {} == 0, "Big endian values should be default constructed in a constexpr context.");
+
+static_assert(BigEndian<u32> { 42 } == 42, "Big endian values should be value constructed in a constexpr context.");
+
+static_assert(LittleEndian<u32> {} == 0, "Little endian values should be default constructed in a constexpr context.");
+
+static_assert(LittleEndian<u32> { 42 } == 42, "Little endian values should be value constructed in a constexpr context.");
+
+TEST_MAIN(Endian);