如何在 std::forward 的构造函数中使 const 仅左值
How to make const only lvalue in a constructor with std::forward
template < typename T1, typename T2 >
MyClass(T1 && v1, T2 && v2)
: m_v1(std::forward< T1 >(v1))
, m_v2(std::forward< T2 >(v2))
{}
让我们有一个名为 MyClass
的 class,其构造函数如上所示。如果没有 std::forward
我们必须编写 4 个不同的构造函数:
MyClass(SomeType&& v1, SomeType&& v2);
MyClass(SomeType&& v1, const SomeType& v2);
MyClass(const SomeType& v1, SomeType&& v2);
MyClass(const SomeType& v1, const SomeType& v2);
这里我们使用const SomeType&
,因为我们不想改变我们的左值。当然,我们有const_cast
,但是很容易找到这样的cast
。同时,我们使用 std::forward
的模板构造函数生成参数类型如下所示的构造函数:SomeType&
- 没有 const
因此我们可以更改构造函数主体中的左值。
问题:正确的解法是什么?我应该添加 const
(怎么做?)还是以适当的方式编写我的构造函数的主体 - 这样,它们就不会更改左值。在添加 const
的情况下,我们将得到这样的结果: const T1&&
如果我们将右值赋予构造函数,我们将无法移动它,因为它将是常量右值。我想,只有当我们给出左值时,我们才必须添加 const
。
我正在尝试阻止 n = 555;
此处:
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <ciso646>
class A
{
public:
using number_t = std::int32_t;
using string_t = std::string;
template < typename T >
using vector_t = std::vector < T >;
public:
template < typename T1, typename T2, typename T3,
typename Dummy = std::enable_if_t < std::is_same < number_t,
typename std::decay < T1 > ::type > ::value > >
A(T1 && n, T2 && s, T3 && v) :
m_n { std::forward < T1 > (n) },
m_s { std::forward < T2 > (s) },
m_v { std::forward < T3 > (v) }
{
n = 555;
}
public:
number_t m_n;
string_t m_s;
vector_t < number_t > m_v;
};
int main()
{
A::number_t n { 666 };
A::string_t s { "hello" };
A::vector_t < A::number_t > v { 1, 2, 3 };
std::cout << n << std::endl;
A a1(n, s, v);
A a2(1, "hello", std::vector<A::number_t>( { 4, 5, 6 } ));
std::cout << n << std::endl;
A a3(1, "hello", std::vector<int>( { 4, 5, 6 } ));
return 0;
}
I’m trying to prevent n = 555;
here:
您通过转发引用获取了参数。这意味着您的意图是他们推断出的行为最终取决于 caller 提供的内容。
如果调用者提供了一个非const
左值,那么你得到一个非const
左值。如果调用者提供了一个 const
左值,那么这就是你得到的。
由于您打算将这些参数转发到它们的最终对象中,因此您的意图是在传递右值时能够修改它们。因此你不能让他们 const
.
保持原样。防止n = 555;
的办法就是不写.
template < typename T1, typename T2 >
MyClass(T1 && v1, T2 && v2)
: m_v1(std::forward< T1 >(v1))
, m_v2(std::forward< T2 >(v2))
{}
让我们有一个名为 MyClass
的 class,其构造函数如上所示。如果没有 std::forward
我们必须编写 4 个不同的构造函数:
MyClass(SomeType&& v1, SomeType&& v2);
MyClass(SomeType&& v1, const SomeType& v2);
MyClass(const SomeType& v1, SomeType&& v2);
MyClass(const SomeType& v1, const SomeType& v2);
这里我们使用const SomeType&
,因为我们不想改变我们的左值。当然,我们有const_cast
,但是很容易找到这样的cast
。同时,我们使用 std::forward
的模板构造函数生成参数类型如下所示的构造函数:SomeType&
- 没有 const
因此我们可以更改构造函数主体中的左值。
问题:正确的解法是什么?我应该添加 const
(怎么做?)还是以适当的方式编写我的构造函数的主体 - 这样,它们就不会更改左值。在添加 const
的情况下,我们将得到这样的结果: const T1&&
如果我们将右值赋予构造函数,我们将无法移动它,因为它将是常量右值。我想,只有当我们给出左值时,我们才必须添加 const
。
我正在尝试阻止 n = 555;
此处:
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <ciso646>
class A
{
public:
using number_t = std::int32_t;
using string_t = std::string;
template < typename T >
using vector_t = std::vector < T >;
public:
template < typename T1, typename T2, typename T3,
typename Dummy = std::enable_if_t < std::is_same < number_t,
typename std::decay < T1 > ::type > ::value > >
A(T1 && n, T2 && s, T3 && v) :
m_n { std::forward < T1 > (n) },
m_s { std::forward < T2 > (s) },
m_v { std::forward < T3 > (v) }
{
n = 555;
}
public:
number_t m_n;
string_t m_s;
vector_t < number_t > m_v;
};
int main()
{
A::number_t n { 666 };
A::string_t s { "hello" };
A::vector_t < A::number_t > v { 1, 2, 3 };
std::cout << n << std::endl;
A a1(n, s, v);
A a2(1, "hello", std::vector<A::number_t>( { 4, 5, 6 } ));
std::cout << n << std::endl;
A a3(1, "hello", std::vector<int>( { 4, 5, 6 } ));
return 0;
}
I’m trying to prevent
n = 555;
here:
您通过转发引用获取了参数。这意味着您的意图是他们推断出的行为最终取决于 caller 提供的内容。
如果调用者提供了一个非const
左值,那么你得到一个非const
左值。如果调用者提供了一个 const
左值,那么这就是你得到的。
由于您打算将这些参数转发到它们的最终对象中,因此您的意图是在传递右值时能够修改它们。因此你不能让他们 const
.
保持原样。防止n = 555;
的办法就是不写.