简体   繁体   English

带有折叠表达式的模板会创建不需要的参数副本

[英]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 's fold expression .以下应该足够了,因为您可以使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM