将任何类型转换为字符串的 Variadic 函数

Variadic Function that converts any type to string

我正在尝试在 C++ 中使用泛型和可变参数来创建一个方法,该方法接受任何可字符串类型并将其连接成单个字符串。

我正在寻找的功能示例是

stringify(50, 5000.00, "test") 结果应该是 "505000.00test".

您可以简单地使用 std::ostringstream 和 C++17 折叠表达式来做到这一点:

#include <sstream>
#include <iostream>

template <typename... Args>
std::string stringify(Args&&... args)
{
    std::ostringstream str;
    (str << ... << args);
    return str.str();
}

live example here

这将能够将任何支持 operator << 标准格式流输出的东西连接成 std::string

如果您希望能够在表达式 SFINAE 中调用此函数,您可以将签名修改为

template <typename... Args>
auto stringify(Args&&... args) -> decltype((std::declval<std::ostream>() << ... << args), std::declval<std::ostringstream>().str());

使用C++17 fold-expressions, to_string() (in lieu of the heavier iostreams), and SFINAE

#include <string>
#include <utility>

using std::to_string;
auto to_string(std::string s) noexcept { return std::move(s); }

template <class... T>
auto stringify(T&&... x)
-> decltype((std::string() + ... + to_string(x))) {
    return (std::string() + ... + to_string(x));
}

将无处不在的流插入器实现的优势与 to_string() 的优势相结合,通常性能要好得多,它可以正常工作:

#include <string>
#include <utility>
#include <sstream>

namespace detail {
    using std::to_string;
    auto to_string(std::string s) noexcept { return std::move(s); }

    template <class... T>
    auto stringify(int, T&&... x)
    -> decltype((std::string() + ... + to_string(x))) {
        return (std::string() + ... + to_string(x));
    }

    template <class... T>
    auto stringify(long, T&&... x)
    -> decltype((std::declval<std::ostream&>() << ... << x), std::string()) {
        std::stringstream ss;
        (ss << ... << x);
        return ss.str();
    }
}

template <class... T>
auto stringify(T&&... x)
-> decltype(detail::stringify(1, x...)) {
    return detail::stringify(1, x...);
}