模板收集:
应用std::cout <<和std::to_string
std::vector、std::array和std::tuple
由于在cpp中打印一个向量被证明是惊人的工作量(至少与这个任务的基本程度相比),并且作为再次跨越相同问题的一个步骤,当使用其他容器时,这里有一个更通用的解决方案…
模板收集内容
这个模板集合处理3种容器类型:
Std::vector, Std::array和Std::tuple。
它为这些对象定义了std::to_string(),并可以通过std::cout << container;直接将它们打印出来。
此外,它还为std::string << container定义了<<运算符。
这样就可以以紧凑的方式构造包含这些容器类型的字符串。
From
std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
我们会讲到
std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
Code
您可以交互地测试这段代码:这里。
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <array>
namespace std
{
// declations: needed for std::to_string(std::vector<std::tuple<int, float>>)
std::string to_string(std::string str);
std::string to_string(const char *str);
template<typename T, size_t N>
std::string to_string(std::array<T, N> const& arr);
template<typename T>
std::string to_string(std::vector<T> const& vec);
template<typename... Args>
std::string to_string(const std::tuple<Args...>& tup);
std::string to_string(std::string str)
{
return std::string(str);
}
std::string to_string(const char *str)
{
return std::string(str);
}
template<typename T, size_t N>
std::string to_string(std::array<T, N> const& arr)
{
std::string s="{";
for (std::size_t t = 0; t != N; ++t)
s += std::to_string(arr[t]) + (t+1 < N ? ", ":"");
return s + "}";
}
template<typename T>
std::string to_string(std::vector<T> const& vec)
{
std::string s="[";
for (std::size_t t = 0; t != vec.size(); ++t)
s += std::to_string(vec[t]) + (t+1 < vec.size() ? ", ":"");
return s + "]";
}
// to_string(tuple)
// https://en.cppreference.com/w/cpp/utility/tuple/operator%3D
template<class Tuple, std::size_t N>
struct TupleString
{
static std::string str(const Tuple& tup)
{
std::string out;
out += TupleString<Tuple, N-1>::str(tup);
out += ", ";
out += std::to_string(std::get<N-1>(tup));
return out;
}
};
template<class Tuple>
struct TupleString<Tuple, 1>
{
static std::string str(const Tuple& tup)
{
std::string out;
out += std::to_string(std::get<0>(tup));
return out;
}
};
template<typename... Args>
std::string to_string(const std::tuple<Args...>& tup)
{
std::string out = "(";
out += TupleString<decltype(tup), sizeof...(Args)>::str(tup);
out += ")";
return out;
}
} // namespace std
/**
* cout: cout << continer
*/
template <typename T, std::size_t N> // cout << array
std::ostream& operator <<(std::ostream &out, std::array<T, N> &con)
{
out << std::to_string(con);
return out;
}
template <typename T, typename A> // cout << vector
std::ostream& operator <<(std::ostream &out, std::vector<T, A> &con)
{
out << std::to_string(con);
return out;
}
template<typename... Args> // cout << tuple
std::ostream& operator <<(std::ostream &out, std::tuple<Args...> &con)
{
out << std::to_string(con);
return out;
}
/**
* Concatenate: string << continer
*/
template <class C>
std::string operator <<(std::string str, C &con)
{
std::string out = str;
out += std::to_string(con);
return out;
}
#define STR() std::string("")
int main()
{
std::array<int, 3> arr {1, 2, 3};
std::string sArr = std::to_string(arr);
std::cout << "std::array" << std::endl;
std::cout << "\ttest to_string: " << sArr << std::endl;
std::cout << "\ttest cout <<: " << arr << std::endl;
std::cout << "\ttest string <<: " << (std::string() << arr) << std::endl;
std::vector<std::string> vec {"a", "b"};
std::string sVec = std::to_string(vec);
std::cout << "std::vector" << std::endl;
std::cout << "\ttest to_string: " << sVec << std::endl;
std::cout << "\ttest cout <<: " << vec << std::endl;
std::cout << "\ttest string <<: " << (std::string() << vec) << std::endl;
std::tuple<int, std::string> tup = std::make_tuple(5, "five");
std::string sTup = std::to_string(tup);
std::cout << "std::tuple" << std::endl;
std::cout << "\ttest to_string: " << sTup << std::endl;
std::cout << "\ttest cout <<: " << tup << std::endl;
std::cout << "\ttest string <<: " << (std::string() << tup) << std::endl;
std::vector<std::tuple<int, float>> vt {std::make_tuple(1, .1), std::make_tuple(2, .2)};
std::string sVt = std::to_string(vt);
std::cout << "std::vector<std::tuple>" << std::endl;
std::cout << "\ttest to_string: " << sVt << std::endl;
std::cout << "\ttest cout <<: " << vt << std::endl;
std::cout << "\ttest string <<: " << (std::string() << vt) << std::endl;
std::cout << std::endl;
std::string s1 = "s1: " + std::to_string(arr) + "; " + std::to_string(vec) + "; " + std::to_string(tup);
std::cout << s1 << std::endl;
std::string s2 = STR() << "s2: " << arr << "; " << vec << "; " << tup;
std::cout << s2 << std::endl;
return 0;
}
输出
std::array
test to_string: {1, 2, 3}
test cout <<: {1, 2, 3}
test string <<: {1, 2, 3}
std::vector
test to_string: [a, b]
test cout <<: [a, b]
test string <<: [a, b]
std::tuple
test to_string: (5, five)
test cout <<: (5, five)
test string <<: (5, five)
std::vector<std::tuple>
test to_string: [(1, 0.100000), (2, 0.200000)]
test cout <<: [(1, 0.100000), (2, 0.200000)]
test string <<: [(1, 0.100000), (2, 0.200000)]
s1: {1, 2, 3}; [a, b]; (5, five)
s2: {1, 2, 3}; [a, b]; (5, five)