Variadic Функция, которая преобразует любой тип в строку - PullRequest
0 голосов
/ 19 апреля 2019

Я пытаюсь использовать generics и varargs в c ++, чтобы создать метод, который принимает любой строковый тип и объединяет его в одну строку.

Примером функциональности, которую я ищу, является

stringify (50, 5000.00, "test"), и результат должен быть "505000.00test".

Ответы [ 2 ]

2 голосов
/ 19 апреля 2019

Вы можете просто использовать std :: ostringstream и C ++ 17-кратное выражение, чтобы сделать это:

#include <sstream>
#include <iostream>

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

живой пример здесь

Это позволит объединить любой набор вещей, поддерживающих operator << для стандартного форматированного потока, в std::string

Если вы хотите иметь возможность использовать вызов этогоФункция в выражении SFINAE, вы можете изменить подпись, чтобы быть

template <typename... Args>
auto stringify(Args&&... args) -> decltype((std::declval<std::ostream>() << ... << args), std::declval<std::ostringstream>().str());
1 голос
/ 19 апреля 2019

Использование C ++ 17 выражений фолда , to_string() (вместо более тяжелых iostreams) и 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() s, как правило, намного лучшей производительности, где она вообще работает:

#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...);
}
...