Преобразование всех аргументов variadi c в одну std :: string с помощью семантики перемещения - PullRequest
1 голос
/ 12 февраля 2020

У меня есть класс, который содержит лямбда-функцию, которая выглядит следующим образом:

class Foo {
private:
    inline static std::string text{};

public:
    template<typename...T>
    inline static auto func = [](T&&...args) mutable throw() {
        text += std::string(args...);
    };

    void show() {
        std::cout << text << '\n';
    }
};

Мое предполагаемое использование будет выглядеть примерно так:

int main() {
    Foo bar;
    bar.func<std::string, int, std::string>( "Hello, I am", 39, "years old!");
    bar.show();
    return 0;
}

Я хочу шаблонные варианты c лямбда, чтобы принимать любой тип параметра, который является базовым c типом, таким как string, char*, char[], int, float, double, et c .. и преобразовать их все в одну строку std :: string, которая будет храниться в классе.

Когда я запускаю свой код так:

int main() {
    Foo bar;
    bar.func<string>( "Hello world!");
    bar.show();
    return 0;
}

Однако все компилируется нормально Когда я начинаю добавлять в различные типы, такие как пример из предполагаемого использования выше, он не компилируется. Microsoft Visual Studio выдает ошибку C2400: невозможно преобразовать список инициализации в std :: string. Ни один конструктор не мог принять тип источника, или разрешение перегрузки конструктора было неоднозначным ...

Мне кажется, я понимаю, почему это неоднозначно, так как это не так уж и проблема. Мой вопрос заключается в том, что было бы правильным и эффективным способом использования «семантики перемещения или идеальной пересылки»? Я пытаюсь избежать кучу временных копий.

1 Ответ

3 голосов
/ 12 февраля 2020

Вы можете использовать выражения сгиба:

template<typename...T>
inline static auto func = [](T&&...args) mutable throw() {
    text += (toString(args) + ...);
};

, где toString определяется как:

template<class T>
std::string toString(T&& t){
    if constexpr (std::is_arithmetic_v<std::decay_t<T>>)
        return std::to_string(std::forward<T>(t));
    else
        return std::forward<T>(t);
}

, вы можете расширить toString для обработки всех типов, которые необходимо преобразовать в string. Демо

...