[英]Template with fold expression creates unwanted parameter copy
The following prototype is intended to make synchronized print:以下原型旨在进行同步打印:
#include <iostream>
#include <string>
#include <sstream>
#include <mutex>
#include <Windows.h> // for OutputDebugString
std::mutex sync_mutex;
template<typename T>
void sync_print_impl(std::ostringstream& str, const T& t)
{
str << t << " ";
}
template<typename ... Args>
void sync_print_impl(std::ostringstream& str, Args ... args)
{
str; // prevents unused variable warning when sync_print is called without arguments
(..., sync_print_impl(str, args));
}
template <typename... Args>
void sync_print(Args... args)
{
std::ostringstream s;
sync_print_impl(s, args...);
{
std::lock_guard<std::mutex> lg(sync_mutex);
std::cout << s.str() << std::endl;
}
}
Simple test is OK:简单测试即可:
void test1()
{
sync_print("abc", 1, 5.5); // prints abc 1 5.5
sync_print(); // prints empty string
}
The following test shows, that parameters are copied:以下测试表明,参数被复制:
class test_class
{
public:
test_class(int n)
: data(n)
{
OutputDebugString(L"test_class\n");
}
test_class(const test_class& other)
{
data = other.data;
OutputDebugString(L"copy constructor\n");
}
test_class& operator=(const test_class& other)
{
data = other.data;
OutputDebugString(L"operator=\n");
return *this;
}
~test_class()
{
OutputDebugString(L"~test_class\n");
}
friend std::ostream& operator<<(std::ostream& os, const test_class& t);
private:
int data{};
};
std::ostream& operator<<(std::ostream& os, const test_class& t)
{
os << t.data;
return os;
}
void test2()
{
test_class t(5);
sync_print(t); // prints 5
}
OutputDebugString
result is: OutputDebugString
结果是:
test_class copy constructor ~test_class ~test_class
How to change sync_print
to ensure that parameters are passed by reference?如何更改
sync_print
以确保通过引用传递参数?
You do not need extra template function sync_print_impl
.您不需要额外的模板函数
sync_print_impl
。 Following should be enough, as you can make use of c++17 's fold expression .以下应该足够了,因为您可以使用c++17的fold expression 。
In addition, use perfect forwarding to avoid coping the object.此外,使用完美转发避免应对对象。
template<typename... Args>
void sync_print_impl(std::ostringstream& str, Args&&... args)
// ^^^^^^^^^^^^^^^^
{
((str << std::forward<Args>(args) << " "), ...);
}
template <typename... Args>
void sync_print(Args&&... args)
// ^^^^^^^^^^^^^^^
{
std::ostringstream s;
sync_print_impl(s, std::forward<Args>(args)...);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// ... code
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.