【问题标题】:Converting all variadic arguments into a single std::string via move semantics通过移动语义将所有可变参数转换为单个 std::string
【发布时间】:2020-05-27 22:26:44
【问题描述】:

我有一个包含 lambda 函数的类,如下所示:

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;
}

我希望模板化的可变参数 lambda 接收任何类型的基本类型参​​数,例如 stringchar*char[]intfloatdouble 等。 . 并将它们全部转换为单个 std::string 将存储在类中。

当我这样运行我的代码时:

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

一切都编译得很好,但是,当我开始添加各种类型时,例如上面预期用途的示例,它无法编译。 Microsoft Visual Studio 给了我一个C2400 编译器错误:无法从初始化列表转换为 std::string。没有构造函数可以采用源类型,或者构造函数重载决议不明确......

我相信我理解为什么它会模棱两可,因为这不是问题所在。我的问题是使用“移动语义或完美转发”的正确有效方式是什么?我试图避免一堆临时副本。

【问题讨论】:

  • 拜托,您能否添加一个导致编译器错误的示例(调用)?
  • @max66 预期用途是产生错误的用途。

标签: string lambda c++17 move variadic


【解决方案1】:

你可以使用折叠表达式:

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 的所有类型。 Demo

【讨论】:

  • 嗯,折叠表达式在这里效果很好!代码编译、运行并打印出预期的结果,除了一个小细节。使用上面的示例调用,输出显示为:“我是 39 岁”。所以现在我需要一种方法在每个可变参数之间包含一个空格,但不是在第一个之前也不是在最后一个之后......
猜你喜欢
  • 2014-11-19
  • 2015-10-13
  • 2016-01-28
  • 2021-10-18
  • 1970-01-01
相关资源
最近更新 更多