将可变参数模板转发给几个类成员

Jam*_*mes 4 c++ templates perfect-forwarding c++11

以下是安全的吗?第一类成员初始化后不会std::string被发现move吗?打印出来好,但我不确定.

template <typename T>
class Test
{
public:

    template <typename... Args>
    Test(Args&&... args)
    :  m_one(new T(std::forward<Args>(args)...)),
       m_two(new T(std::forward<Args>(args)...))    // <- Here
    {
    }

private:
    std::unique_ptr<T> m_one;
    std::unique_ptr<T> m_two;
};


class C
{ 
public:

    C(int a, int b, const std::string& c)
    :  m_a(a),
       m_b(b),
       m_c(c)
    {
        std::cout << "ctor a=" << m_a << ", b=" << m_b << ", c=" << m_c << "\n";
    }

    int m_a;
    int m_b;
    std::string m_c;
};


int main()
{
     Test<C> t(1, 2, "3");
}
Run Code Online (Sandbox Code Playgroud)

我想这是好的,因为第三个ctor参数Cconst std::string&,但是如何防止在一个采用r值ref的类中进行完美转发,例如,C(int, int, std::string&&)因为那时m_two不会收到相同的ctor args m_one

将测试的ctor更改为

   template <typename... Args>
   Test(Args&... args)
Run Code Online (Sandbox Code Playgroud)

不编译.也没有删除std::forward<Args>(args)...来自m_onem_twoctors.

Vau*_*ato 7

你会想要使用这样的东西:

#include <memory>
#include <string>
#include <iostream>
#include <utility>

template <typename T>
class Test
{
public:

    template <typename... Args>
    Test(Args&&... args)
    :  m_one(new T(args...)),                    // avoid moving the first time
       m_two(new T(std::forward<Args>(args)...)) // but allowing moving the last time
    {
    }

private:
    std::unique_ptr<T> m_one;
    std::unique_ptr<T> m_two;
};


class C
{
public:

    C(int a, int b, std::string c) // rule of thumb -- if you are going to copy an argument
                                   // anyway, pass it by value.
    :  m_a(a),
       m_b(b),
       m_c(std::move(c)) // you can safely move here since it is the last use. 
    {
        std::cout << "ctor a=" << m_a << ", b=" << m_b << ", c=" << m_c << "\n";
    }

    int m_a;
    int m_b;
    std::string m_c;
};
Run Code Online (Sandbox Code Playgroud)

因为m_one,参数使用左值引用,因此不会发生移动.因为m_two,std::forward将使用适当的右值引用.以该std::string参数C的值,并使用std::move使其成为任何一种情况下正常工作.如果传递左值引用,则参数将被复制构造,但是如果传递右值引用,则参数将被移动构造.在任何一种情况下,您都可以将参数移动到您的m_c成员中以提高效率.