Add a tuple type for packing

At the top level, payload had the ability to pack a tuple, but it did it
by splitting it into its parts and packing those individually. But if
one of those parts was a tuple, it would fail. This moves the tuple
packing code into the packing templates so that it is possible to pack a
nested tuple of tuples.

Tested-by: newly written tuple unit tests pass

Change-Id: Icd80926314072df78b0083a823dcfb46e944e365
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/include/ipmid/message.hpp b/include/ipmid/message.hpp
index 4079eab..030618f 100644
--- a/include/ipmid/message.hpp
+++ b/include/ipmid/message.hpp
@@ -252,24 +252,6 @@
         return packRet;
     }
 
-    /**
-     * @brief pack a tuple of values (of any supported type) into the buffer
-     *
-     * This will pack the elements of the tuple as if each one was passed in
-     * individually, as if passed into the above variadic function.
-     *
-     * @tparam Types - the implicitly declared list of the tuple element types
-     *
-     * @param t - the tuple of values to pack
-     *
-     * @return int - non-zero on pack errors
-     */
-    template <typename... Types>
-    int pack(std::tuple<Types...>& t)
-    {
-        return std::apply([this](Types&... args) { return pack(args...); }, t);
-    }
-
     /******************************************************************
      * Request operations
      *****************************************************************/
diff --git a/include/ipmid/message/pack.hpp b/include/ipmid/message/pack.hpp
index 8a9abe1..4314ac1 100644
--- a/include/ipmid/message/pack.hpp
+++ b/include/ipmid/message/pack.hpp
@@ -93,6 +93,17 @@
     }
 };
 
+/** @brief Specialization of PackSingle for std::tuple<T> */
+template <typename... T>
+struct PackSingle<std::tuple<T...>>
+{
+    static int op(Payload& p, const std::tuple<T...>& v)
+    {
+        return std::apply([&p](const T&... args) { return p.pack(args...); },
+                          v);
+    }
+};
+
 /** @brief Specialization of PackSingle for std::string
  *  represented as a UCSD-Pascal style string
  */