fix: UtilAll::to_string convert the value of bool to 0/1 (#334)

Co-authored-by: shenhui.backend <shenhui.backend@bytedance.com>
diff --git a/src/common/UtilAll.h b/src/common/UtilAll.h
index 4f34419..ec4ea30 100644
--- a/src/common/UtilAll.h
+++ b/src/common/UtilAll.h
@@ -41,6 +41,7 @@
 #include <fstream>
 #include <map>
 #include <sstream>
+#include <type_traits>
 #include "RocketMQClient.h"
 
 using namespace std;
@@ -93,6 +94,43 @@
 #define SIZET_FMT "%zu"
 #endif
 
+namespace detail {
+
+template <typename T, bool = false>
+struct UseStdToString {
+  typedef std::false_type type;
+};
+
+template <typename T>
+struct UseStdToString<T, true> {
+  typedef std::true_type type;
+};
+
+template <typename T>
+inline std::string to_string(const T& v, std::false_type) {
+  std::ostringstream stm;
+  stm << v;
+  return stm.str();
+}
+
+template <typename T>
+inline std::string to_string(const T& v, std::true_type) {
+  return std::to_string(v);
+}
+
+template <typename T>
+inline std::string to_string(const T& v) {
+  return to_string(v, typename UseStdToString < T,
+                   std::is_arithmetic<T>::value && !std::is_same<bool, typename std::decay<T>::type>::value > ::type{});
+}
+
+template <>
+inline std::string to_string<bool>(const bool& v) {
+  return v ? "true" : "false";
+}
+
+}  // namespace detail
+
 //<!************************************************************************
 class UtilAll {
  public:
@@ -107,9 +145,7 @@
 
   template <typename T>
   static string to_string(const T& n) {
-    std::ostringstream stm;
-    stm << n;
-    return stm.str();
+    return detail::to_string(n);
   }
 
   static bool to_bool(std::string const& s) { return atoi(s.c_str()); }
diff --git a/test/src/protocol/CommandHeaderTest.cpp b/test/src/protocol/CommandHeaderTest.cpp
index 9e043cc..8ce2d59 100644
--- a/test/src/protocol/CommandHeaderTest.cpp
+++ b/test/src/protocol/CommandHeaderTest.cpp
@@ -88,7 +88,7 @@
   EXPECT_EQ(requestMap["group"], group);
   EXPECT_EQ(requestMap["delayLevel"], "2");
   EXPECT_EQ(requestMap["offset"], "3027");
-  EXPECT_EQ(requestMap["unitMode"], "1");
+  EXPECT_EQ(requestMap["unitMode"], "true");
   EXPECT_EQ(requestMap["originMsgId"], originMsgId);
   EXPECT_EQ(requestMap["originTopic"], originTopic);
   EXPECT_EQ(requestMap["maxReconsumeTimes"], "12");
@@ -98,7 +98,7 @@
   EXPECT_EQ(outData["group"], group);
   EXPECT_EQ(outData["delayLevel"], 2);
   EXPECT_EQ(outData["offset"], "3027");
-  EXPECT_EQ(outData["unitMode"], "1");
+  EXPECT_EQ(outData["unitMode"], "true");
   EXPECT_EQ(outData["originMsgId"], originMsgId);
   EXPECT_EQ(outData["originTopic"], originTopic);
   EXPECT_EQ(outData["maxReconsumeTimes"], 12);
@@ -197,7 +197,7 @@
   EXPECT_EQ(requestMap["tranStateTableOffset"], "1000");
   EXPECT_EQ(requestMap["commitLogOffset"], "2000");
   EXPECT_EQ(requestMap["commitOrRollback"], "3000");
-  EXPECT_EQ(requestMap["fromTransactionCheck"], "1");
+  EXPECT_EQ(requestMap["fromTransactionCheck"], "true");
 
   Value outData;
   header.Encode(outData);
@@ -207,7 +207,7 @@
   EXPECT_EQ(outData["tranStateTableOffset"], "1000");
   EXPECT_EQ(outData["commitLogOffset"], "2000");
   EXPECT_EQ(outData["commitOrRollback"], "3000");
-  EXPECT_EQ(outData["fromTransactionCheck"], "1");
+  EXPECT_EQ(outData["fromTransactionCheck"], "true");
 
   EXPECT_NO_THROW(header.toString());
 }
@@ -251,8 +251,8 @@
   EXPECT_EQ(requestMap["flag"], "5");
   EXPECT_EQ(requestMap["properties"], properties);
   EXPECT_EQ(requestMap["reconsumeTimes"], "6");
-  EXPECT_EQ(requestMap["unitMode"], "1");
-  EXPECT_EQ(requestMap["batch"], "0");
+  EXPECT_EQ(requestMap["unitMode"], "true");
+  EXPECT_EQ(requestMap["batch"], "false");
 
   Value outData;
   header.Encode(outData);
@@ -266,8 +266,8 @@
   EXPECT_EQ(outData["flag"], flag);
   EXPECT_EQ(outData["properties"], properties);
   EXPECT_EQ(outData["reconsumeTimes"], "6");
-  EXPECT_EQ(outData["unitMode"], "1");
-  EXPECT_EQ(outData["batch"], "0");
+  EXPECT_EQ(outData["unitMode"], "true");
+  EXPECT_EQ(outData["batch"], "false");
 }
 
 TEST(commandHeader, SendMessageRequestHeaderV2) {
@@ -309,8 +309,8 @@
   EXPECT_EQ(requestMap["h"], "5");
   EXPECT_EQ(requestMap["i"], properties);
   EXPECT_EQ(requestMap["j"], "6");
-  EXPECT_EQ(requestMap["k"], "1");
-  EXPECT_EQ(requestMap["m"], "0");
+  EXPECT_EQ(requestMap["k"], "true");
+  EXPECT_EQ(requestMap["m"], "false");
 
   Value outData;
   header.Encode(outData);
@@ -324,8 +324,8 @@
   EXPECT_EQ(outData["h"], flag);
   EXPECT_EQ(outData["i"], properties);
   EXPECT_EQ(outData["j"], "6");
-  EXPECT_EQ(outData["k"], "1");
-  EXPECT_EQ(outData["m"], "0");
+  EXPECT_EQ(outData["k"], "true");
+  EXPECT_EQ(outData["m"], "false");
 
   SendMessageRequestHeader v1;
   header.CreateSendMessageRequestHeaderV1(v1);
@@ -523,7 +523,7 @@
   header.SetDeclaredFieldOfCommandHeader(requestMap);
   EXPECT_EQ(requestMap["clientId"], "testClientId");
   EXPECT_EQ(requestMap["consumerGroup"], "testConsumer");
-  EXPECT_EQ(requestMap["jstackEnable"], "1");
+  EXPECT_EQ(requestMap["jstackEnable"], "true");
 
   Value outData;
   header.Encode(outData);