可变参数函数,可将任何类型转换为字符串

时间:2019-04-19 20:39:18

标签: c++ string variadic-functions

我正在尝试在c ++中使用泛型和varargs来创建一个接受任何可字符串化类型并将其连接为单个字符串的方法。

我正在寻找的功能的一个例子是

stringify(50,5000.00,“ test”),结果应为“ 505000.00test”。

2 个答案:

答案 0 :(得分:2)

您只需使用std::ostringstream和C ++ 17 fold表达式即可:

#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());

答案 1 :(得分:1)

使用C++17 fold-expressionsto_string()(代替较重的iostream)和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...);
}