由于并非所有地方都支持std::format
,而且我不想再添加像fmt
这样的大型依赖项,因此我希望能够快速制作自己的to_string
解决方案以处理多种类型。以下是代码。
#include <ranges>
#include <string>
#include <concepts>
template<typename Type>
constexpr std::string stringify(const Type &data) noexcept;
template<typename Type> requires std::integral<Type>
constexpr std::string stringify(const Type &data) noexcept {
return std::to_string(data);
}
template<typename Type>
constexpr std::string stringify_inner(const Type &data) noexcept {
return stringify(data);
}
template<typename Type> requires std::ranges::range<Type>
constexpr std::string stringify_inner(const Type &data) noexcept {
return "[" + stringify(data) + "]";
}
template<typename Type> requires std::ranges::range<Type>
constexpr std::string stringify(const Type &data) noexcept {
std::string string;
for (auto &i : data) {
string += stringify_inner(i);
string += ", ";
}
string.pop_back();
string.pop_back();
return string;
}
现在,如果我编写以下代码,将会获得一些不错的输出。
int main() {
std::vector<int> a = { 1, 2, 3, 4 };
std::vector<std::vector<int>> b = {{ 1, 2 }, { 3, 4 }};
std::cout << stringify(a) << std::endl;
std::cout << stringify(b) << std::endl;
}
// >>> 1, 2, 3, 4
// >>> [1, 2], [3, 4]
现在,由于某些原因,如果我删除
stringify<std::vector<int>>
调用,编译器将无法推断出正确的函数。int main() {
// std::vector<int> a = { 1, 2, 3, 4 };
std::vector<std::vector<int>> b = {{ 1, 2 }, { 3, 4 }};
// std::cout << stringify(a) << std::endl;
std::cout << stringify(b) << std::endl;
}
// >>> undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>,
// >>> std::allocator<char> > stringify<std::vector<int, std::allocator<int> > >(std::vector<int,
// >>> std::allocator<int> > const&)'
我认为我理解这里发生了什么,但我不知道为什么或如何修复它。似乎编译器需要手动实例化stringify<std::vector<int>>
,以便可以解析stringify<std::vector<std::vector<int>>>
。
我以前从未遇到过这种行为,并且不知道如何继续。我正在使用Windows上的GCC编译C++20。谢谢。
stringify_inner
函数之前提前声明你的最后一个函数可能会解决这个问题。stringify_inner
只知道整数类型的特化,因此假定未实现的第一个声明是它应该使用的声明。 - Alan Birtlesinline function 'stringify<std::vector<int>>' is not defined [-Wundefined-inline]
。 - Enlicoconstexpr
,但那是另一个时间的问题。 - Jaanstringify<std::vector<int>>
,我认为这将打败使用std::ranges::range<T>
获取任何有效范围的目的。 - Jaan