通过移动语义将所有可变参数转换为单个 std::string
Converting all variadic arguments into a single std::string via move semantics
我有一个 class,其中包含如下所示的 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 接受任何类型的基本类型参数,例如 string
、char*
、char[]
、int
、float
、double
等...并将它们全部转换为单个 std::string 并将存储在 class.
中
当我 运行 我的代码是这样的:
int main() {
Foo bar;
bar.func<string>( "Hello world!");
bar.show();
return 0;
}
一切都可以正常编译,但是,当我开始添加各种类型时,例如上面预期用途的示例,它无法编译。 Microsoft Visual Studio 给我一个 C2400
编译器错误:无法从初始化列表转换为 std::string。没有构造函数可以采用源类型,或者构造函数重载决策不明确...
我相信我理解为什么它是模棱两可的,因为这不是问题所在。我的问题是使用 "move semantics or perfect forwarding" 的正确有效方法是什么?我试图避免一堆临时副本。
您可以使用折叠表达式:
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
我有一个 class,其中包含如下所示的 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 接受任何类型的基本类型参数,例如 string
、char*
、char[]
、int
、float
、double
等...并将它们全部转换为单个 std::string 并将存储在 class.
当我 运行 我的代码是这样的:
int main() {
Foo bar;
bar.func<string>( "Hello world!");
bar.show();
return 0;
}
一切都可以正常编译,但是,当我开始添加各种类型时,例如上面预期用途的示例,它无法编译。 Microsoft Visual Studio 给我一个 C2400
编译器错误:无法从初始化列表转换为 std::string。没有构造函数可以采用源类型,或者构造函数重载决策不明确...
我相信我理解为什么它是模棱两可的,因为这不是问题所在。我的问题是使用 "move semantics or perfect forwarding" 的正确有效方法是什么?我试图避免一堆临时副本。
您可以使用折叠表达式:
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