子类化 std::optional时编译错误
Compile error while subclassing std::optional
>我正在尝试在 MS C++17 (VS2017) 中子类 std::optional 以向类添加消息字段,但收到编译错误
错误 C2280:"
OptMsg<bool>::OptMsg(const OptMsg<bool> &)
":尝试引用已删除的函数
智能感知提供了更多的见解:
函数"
OptMsg<T>::OptMsg(const OptMsg<bool> &) throw() [with T=bool]
"(隐式声明)不能被引用——它是一个已删除的函数
这告诉我编译器在引用已删除函数抛出时我的复制构造函数有问题?我收到错误,从函数返回一个实例。例如,
OptMsg<bool> foo()
{
OptMsg<bool> res = false;
return res; // <-- Getting compile error here
}
这是我的课。任何见解都值得赞赏!
template <class T>
class KB_MAPPING_ENGINE_API OptMsg : public std::optional<T>
{
public:
constexpr OptMsg() noexcept
: optional{}
{}
constexpr OptMsg(std::nullopt_t) noexcept
: optional{}
{}
constexpr OptMsg(const T & other) noexcept
: optional<T>{other}
, m_Message{other.m_Message}
{}
constexpr explicit OptMsg(const T && other) noexcept
: optional<T>{other}
, m_Message{other.m_Message}
{}
OptMsg & operator = ( const OptMsg & other ) noexcept
{
if ( &other != this )
m_Message = other.m_Message;
return *this;
}
OptMsg && operator = ( const OptMsg && other )
{
if ( &other != this )
m_Message = other.m_Message;
return *this;
}
void SetMessage( const std::string & message ) { m_Message = message; }
std::string GetMessage() { return m_Message; }
private:
std::string m_Message;
};
告诉我编译器与我的复制构造函数有问题 引用已删除的函数抛出?
不,没有功能throw()
。此表示法是 C++11 之前声明函数不会抛出任何内容的方式。如今noexcept
推荐,但显然,Microsoft还没有赶上......
相反,该错误告诉您正在尝试调用复制构造函数(在您标记的行中),但您的类没有!
为什么没有?这里
constexpr OptMsg(const T & other) noexcept
: optional<T>{other}
, m_Message{other.m_Message}
{}
看起来它打算成为复制构造函数。但是,这并不是因为论点const T&
.复制构造函数需要const OptMsg&
.
通常,会自动为您声明复制构造函数。这里没有发生这种情况,因为您明确声明了operator=(const OptMsg&)
.因此,错误消息提到您的复制构造函数是一个"已删除的函数"。
如何解决?
正确声明复制构造函数,或删除赋值运算符。编译器将为您生成一个。 但请注意,您当前的赋值运算符实现(复制和移动)仅分配消息,而不分配optional
本身。这是有意的吗?将是一个非常意想不到的行为...如果这是有意的,您必须自己声明所有内容(但正确!
但是假设这不是故意的,并且进一步假设您的复制操作只是简单地复制整个实例(消息 + 基类),那么自动生成的构造函数和赋值运算符完全可以执行您想要的操作,而无需自己编写它们。但是,您可以将其写入您的类中,让每个人都立即看到您正在使用编译器生成的:
constexpr OptMsg() = default;
constexpr OptMsg(const OptMsg & other) = default;
constexpr OptMsg(OptMsg && other) = default;
OptMsg & operator = ( const OptMsg & other ) = default;
OptMsg & operator = ( OptMsg && other ) = default;
更新:
请注意,移动构造函数和移动赋值运算符需要OptMsg&&
作为参数。你一直有const OptMsg&&
.因此您的错误消息
"运算符 =(const OptMsg &&)':不是可以默认的特殊成员函数
还可以看看零规则(感谢@Caleth)。
我发现了一些问题,例如:
constexpr explicit OptMsg(const T && other) noexcept
: optional<T>{other}
, m_Message{other.m_Message}
{}
我相信你的意思是
constexpr explicit OptMsg( OptMsg&& other) noexcept
: optional<T>{std::forward<OptMsg>(other)}
, m_Message{other.m_Message}
{}
这里有两点意见: 移动不是恒定的!源数据可能会被修改,以识别数据的所有权已被移动! 您必须使用std::forward
将右值引用转发到基类移动构造函数。
还有你的:
std::string GetMessage() const { return m_Message; }
必须标记const
!
接下来的事情:
constexpr OptMsg( const T& value ): OptMsg::optional{ value }{}
不能标记为explicit
因为它专用于从 bool->OptMsg 进行类型转换
- std::is_base_of表示ctor编译错误
- Qt5:使用QCommandLineParser类时出现奇怪的编译错误
- 如何修复sfml c++代码编译错误
- 使用 MATLAB 编码器生成C++代码:编译错误"undefined reference to `rgb2gray_tbb_real64'"
- 使用外部SDK工具链文件在VisualStudio上生成项目编译错误
- vscode下的Arduino代码出现意外编译错误
- 第三方 API 中的编译错误 - Visual Studio
- std::cout输出int时出现编译错误
- 奇怪的代码抛出编译错误模板< J,int aSize=10> C2143:语法错误:在"<"之前缺少";"
- 提升图广度优先搜索前置编译错误
- C++ 中的编译错误:未定义对"主"的引用 collect2:错误:ld 返回 1 个退出状态
- 使用带有 ref 参数的成员函数创建线程时出现编译错误
- 我在C++中遇到了这个奇怪的编译错误
- 在C++中使用 Catch 测试框架编译错误"error: expected ';' at end of declaration list"
- 使用 std::enable_if 限制派生类的模板参数时出现编译错误
- 现代OpenGL和GLEW Libraray的编译错误
- C++ 编译错误:意外的类型名称"字符串":预期的表达式
- C ++程序编译错误,找不到/访问文件
- 使用直接大括号初始化时,C++ 编译错误"声明末尾的预期";"
- 为什么传递非静态成员函数会导致编译错误?