message: append: support span

Change how we detect the ability to iterate over a type so that
it supports additional types, such as span.  Add test case to cover
span.  Add some static_asserts in the test cases to ensure we are
triggering the correct add_multiple/add_single paths for a few
assorted types.

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I42ff496ab58af613940c9ceb979c71f468f125fc
diff --git a/include/sdbusplus/utility/container_traits.hpp b/include/sdbusplus/utility/container_traits.hpp
index 2ad993a..190252b 100644
--- a/include/sdbusplus/utility/container_traits.hpp
+++ b/include/sdbusplus/utility/container_traits.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <utility>
+
 namespace sdbusplus
 {
 namespace utility
@@ -22,7 +24,7 @@
     } no;
 
     template <typename C>
-    static constexpr yes test(typename C::const_iterator*);
+    static constexpr yes test(decltype(std::cbegin(std::declval<C>()))*);
     template <typename C>
     static constexpr no test(...);
 
diff --git a/test/message/append.cpp b/test/message/append.cpp
index 720efb8..59e83b4 100644
--- a/test/message/append.cpp
+++ b/test/message/append.cpp
@@ -6,6 +6,7 @@
 #include <array>
 #include <map>
 #include <set>
+#include <span>
 #include <string>
 #include <tuple>
 #include <unordered_map>
@@ -80,6 +81,8 @@
 
 TEST_F(AppendTest, RValueInt)
 {
+    static_assert(
+        sdbusplus::message::details::can_append_multiple_v<decltype(1)>);
     expect_basic<int>(SD_BUS_TYPE_INT32, 1);
     new_message().append(1);
 }
@@ -87,6 +90,8 @@
 TEST_F(AppendTest, LValueInt)
 {
     const int a = 1;
+    static_assert(
+        sdbusplus::message::details::can_append_multiple_v<decltype(a)>);
     expect_basic<int>(SD_BUS_TYPE_INT32, a);
     new_message().append(a);
 }
@@ -154,6 +159,8 @@
 TEST_F(AppendTest, XValueCString)
 {
     const char* s = "asdf";
+    static_assert(
+        sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
     expect_basic_string(SD_BUS_TYPE_STRING, s);
     new_message().append(std::move(s));
 }
@@ -167,6 +174,8 @@
 TEST_F(AppendTest, LValueString)
 {
     std::string s{"asdf"};
+    static_assert(
+        !sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
     expect_basic_string(SD_BUS_TYPE_STRING, s.c_str());
     new_message().append(s);
 }
@@ -213,6 +222,8 @@
 TEST_F(AppendTest, Array)
 {
     const std::array<double, 4> a{1.1, 2.2, 3.3, 4.4};
+    static_assert(
+        !sdbusplus::message::details::can_append_multiple_v<decltype(a)>);
 
     {
         testing::InSequence seq;
@@ -226,6 +237,25 @@
     new_message().append(a);
 }
 
+TEST_F(AppendTest, Span)
+{
+    const std::array<double, 4> a{1.1, 2.2, 3.3, 4.4};
+    auto s = std::span{a};
+    static_assert(
+        !sdbusplus::message::details::can_append_multiple_v<decltype(s)>);
+
+    {
+        testing::InSequence seq;
+        expect_open_container(SD_BUS_TYPE_ARRAY, "d");
+        for (const auto& i : s)
+        {
+            expect_basic<double>(SD_BUS_TYPE_DOUBLE, i);
+        }
+        expect_close_container();
+    }
+    new_message().append(s);
+}
+
 TEST_F(AppendTest, Vector)
 {
     const std::vector<int> v{1, 2, 3, 4};