[英]Forward variadic template args to several class members
Is the following safe? 以下是安全的吗? Won't the
std::string
be move
d after the first class member is initialised? 初始化第一个类成员后,
std::string
不会move
吗? It prints out ok but I'm not sure. 打印出来好,但我不确定。
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");
}
I guess it's ok since the third ctor param of C
is const std::string&
, but how do I prevent perfect forwarding in a class that takes an r-value ref, eg C(int, int, std::string&&)
as then m_two
will not receive the same ctor args as m_one
? 我想这没关系,因为
C
的第三个ctor参数是const std::string&
,但是如何在一个带有r值ref的类中阻止完美转发,例如C(int, int, std::string&&)
m_two
不会收到与m_one
相同的ctor args?
Changing the ctor of Test to 将测试的ctor更改为
template <typename... Args>
Test(Args&... args)
doesn't compile. 不编译。 Nor does removing the
std::forward<Args>(args)...
from m_one
and m_two
ctors. 也没有从
m_one
和m_two
中删除std::forward<Args>(args)...
You are going to want to use something like this: 你会想要使用这样的东西:
#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;
};
For m_one
, the arguments use lvalue references, so no moving will take place. 对于
m_one
,参数使用左值引用,因此不会发生移动。 For m_two
, the std::forward
will use rvalue references as appropriate. 对于
m_two
, std::forward
将根据需要使用rvalue引用。 Taking the std::string
argument to C
by value and using std::move
makes it work properly for either case. 将
std::string
参数取值为C
并使用std::move
使其适用于任何一种情况。 If you pass an lvalue reference, then the argument will be copy-constructed, but if you pass an rvalue reference, the argument will be move-constructed. 如果传递左值引用,则参数将被复制构造,但是如果传递右值引用,则参数将被移动构造。 In either case, you can move the argument into your
m_c
member for efficiency. 在任何一种情况下,您都可以将参数移动到
m_c
成员中以提高效率。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.