首先让我简要介绍一下实际情况:
我创建了一个名为error<T>
的类模板,它保存了类型T和与错误相关的变量
构造函数就像这样
error(T&&,..other_params...)
并且有一个生成函数的实用程序函数,其定义如此
template<typename T>
make_error(T&& val_T,..other_params..)
{return error<T>(std::forward<T&&>(val_t),..other_params..);}
我使用此类型作为返回类型而不仅仅是类型T.基本上它只是包含错误信息的类型。
它有一个getter,它获取包含类型的值:
T get()
{ return val_T_int;}
其中val_T_int
与上面的val_t
有关
当我使用仅移动类型时,此get
会出现错误delete copy constructor being used
。
Q1。为什么会这样说?为什么不移动构造值?即我必须在返回值上明确使用std :: move()。
Q2。如果Q1不可能那么我将如何启用这样的功能,而用户而不是返回类型将返回此错误.i无法使用boost::optional
,因为它需要类型为copy constructible
?
我的编译器:Windows 7上的minGW GCC 4.8.2。
例如:
class B //a move only type
{
B( const B& )=delete;
B& operator=( const B& ) = delete;
public:
B( B&& )
{
std::cout << "B&&\n";
}
B& operator=( B&& )
{
std::cout << "B=\n";
return *this;
}
B(){ std::cout << "B()\n"; }
};
struct error //the other parts are stripped of for simplicity.
{
B get()
{
return std::move(b);
}
private :
B b{};// B is a move only type.
};
error er{};
er.get(); //error:use of deleted function B(const B&)!.
我在这里不理解什么? 谢谢你的阅读。
P.S this很接近,但我不明白局部变量的原因。
答案 0 :(得分:1)
您的get()
想要返回一份副本,因此需要copy-ctor。如果您将内部值val_T_int
移至返回值,则表示val_T_int
无效。之后你无法访问它的值,这可能不是你想要的。
想到一个解决方案:不要返回值,只允许(const)访问:
const T& get() const
{
return val_T_int;
}
如果您还需要/需要非const访问,请添加第二个重载:
T& get()
{
return val_T_int;
}
允许您班级的用户甚至修改val_T_int
,例如er.get() = 42;
。
答案 1 :(得分:1)
看看以下代码。如果get
方法会将字符串移出成员变量,那么t
的值应该是多少?
error e = make_error(std::string{"foobar"});
std::string s = e.get();
std::string t = e.get();
您可以返回对成员变量的引用。它可能如下所示:
const T& get() const { return val_T_int; }
该解决方案的问题在于,您无法通过以下方式将其与不可复制类型一起使用:
std::unique_ptr<...> result = make_error(...).get();
但是,您可以使用 rvalue-referenced for this 来解决此问题。如果以下列方式声明get
,则该函数只能用于 temporaries (以及显式移动的对象)。因此,将成员变量移出对象是可以的。
T get() && { return std::move(val_T_int); }