以 "almost always auto" 样式初始化 ZeroMQ 2.2 消息要使用私有构造函数
Initializing ZeroMQ 2.2 message in "almost always auto" style wants to use private constructor
我写了一个使用 ZeroMQ 的 C++11 程序。
在一个特定的行中,我想创建一个新消息作为局部变量,并使用名为 serialized
的向量的大小对其进行初始化,使用 "almost always auto" 风格的语法:
auto zm = zmq::message_t {serialized.size()};
这在我的机器上编译得很好(我们称之为机器“A”;使用 Clang++ 版本 3.4.2-13 并且还使用 g++ 版本 4.9.1),而在同事的机器上(“B”;使用 Clang++版本 3.5.0-10) 出现错误:
error: calling a private constructor of class 'zmq::message_t'
auto zm = zmq::message_t {serialized.size()};
^
/usr/include/zmq.hpp:192:9: note: declared private here
message_t (const message_t&);
^
两台机器都是运行 Debian 8.0 (jessie)。机器 A 安装了 libzmq3-dev installed (ZeroMQ version 4.0.5+dfsg-2), while on machine B libzmq-dev(ZeroMQ 版本 2.2.0+dfsg-6)。在比较各自包中包含的两个版本 zmq.hpp
时,以下部分可能与此问题相关。
在机器 A 上:
class message_t
{
// ...
public:
inline explicit message_t (size_t size_)
{
int rc = zmq_msg_init_size (&msg, size_);
if (rc != 0)
throw error_t ();
}
// ...
#ifdef ZMQ_HAS_RVALUE_REFS
inline message_t (message_t &&rhs) : msg (rhs.msg)
{
int rc = zmq_msg_init (&rhs.msg);
if (rc != 0)
throw error_t ();
}
inline message_t &operator = (message_t &&rhs)
{
std::swap (msg, rhs.msg);
return *this;
}
#endif
// ...
private:
zmq_msg_t msg;
message_t (const message_t&);
void operator = (const message_t&);
};
在机器 B 上:
class message_t : private zmq_msg_t
{
// ...
public:
inline message_t (size_t size_)
{
int rc = zmq_msg_init_size (this, size_);
if (rc != 0)
throw error_t ();
}
// no move constructor/move assignment
// ...
private:
message_t (const message_t&);
void operator = (const message_t&);
};
当我将我的代码更改为这个时
zmq::message_t zmq {serialized.size()};
机器 B 上的错误消失了。
我的问题是:
我打算调用 message_t (size_t)
构造函数。为什么会尝试在机器 B 上使用私有的 message_t (const message_t&)
?
使错误消失的代码更改删除了赋值运算符。为什么编译器不抱怨 void operator = (const message_t&)
是私有的,而是抱怨 message_t (const message_t&)
?
为什么机器A上没有错误,虽然message_t (const message_t&)
在那里也是私有的?我想这与声明 message_t (size_t)
explicit
有关,但我不明白这个关键字的作用。 (edit: 原来我不知道A机版本有move构造函数,B机版本没有。)
转
auto zm = zmq::message_t {serialized.size()};
进入
izmq::message_t zm {serialized.size()};
因为 = 调用(不需要的,私有的)复制构造函数
正在关注
auto zm = zmq::message_t {serialized.size()};
不是作业,
但是使用移动或复制构造函数(可能被省略)初始化 zm
应该可以访问(即使它被省略)。
如预期的那样explicit message_t (size_t)
构建了临时文件。
我怀疑 Clang++ 版本 3.4.2-13 中存在错误,因为您应该遇到与机器 B 中相同的错误。(A 中 B 没有的移动运算符解释这种行为)。
auto zm = zmq::message_t {serialized.size()};
是一个变量声明,所以在这种情况下 = 是一个复制初始化而不是矫揉造作,这就是为什么这是被调用的构造函数而不是矫揉造作的运算符。
显式关键字意味着构造函数仅被考虑用于直接初始化,
就是这种情况
zmq::message_t zmq {serialized.size()};
您可以在此处找到更多详细信息和示例:http://en.cppreference.com/w/cpp/language/explicit
我写了一个使用 ZeroMQ 的 C++11 程序。
在一个特定的行中,我想创建一个新消息作为局部变量,并使用名为 serialized
的向量的大小对其进行初始化,使用 "almost always auto" 风格的语法:
auto zm = zmq::message_t {serialized.size()};
这在我的机器上编译得很好(我们称之为机器“A”;使用 Clang++ 版本 3.4.2-13 并且还使用 g++ 版本 4.9.1),而在同事的机器上(“B”;使用 Clang++版本 3.5.0-10) 出现错误:
error: calling a private constructor of class 'zmq::message_t'
auto zm = zmq::message_t {serialized.size()};
^
/usr/include/zmq.hpp:192:9: note: declared private here
message_t (const message_t&);
^
两台机器都是运行 Debian 8.0 (jessie)。机器 A 安装了 libzmq3-dev installed (ZeroMQ version 4.0.5+dfsg-2), while on machine B libzmq-dev(ZeroMQ 版本 2.2.0+dfsg-6)。在比较各自包中包含的两个版本 zmq.hpp
时,以下部分可能与此问题相关。
在机器 A 上:
class message_t
{
// ...
public:
inline explicit message_t (size_t size_)
{
int rc = zmq_msg_init_size (&msg, size_);
if (rc != 0)
throw error_t ();
}
// ...
#ifdef ZMQ_HAS_RVALUE_REFS
inline message_t (message_t &&rhs) : msg (rhs.msg)
{
int rc = zmq_msg_init (&rhs.msg);
if (rc != 0)
throw error_t ();
}
inline message_t &operator = (message_t &&rhs)
{
std::swap (msg, rhs.msg);
return *this;
}
#endif
// ...
private:
zmq_msg_t msg;
message_t (const message_t&);
void operator = (const message_t&);
};
在机器 B 上:
class message_t : private zmq_msg_t
{
// ...
public:
inline message_t (size_t size_)
{
int rc = zmq_msg_init_size (this, size_);
if (rc != 0)
throw error_t ();
}
// no move constructor/move assignment
// ...
private:
message_t (const message_t&);
void operator = (const message_t&);
};
当我将我的代码更改为这个时
zmq::message_t zmq {serialized.size()};
机器 B 上的错误消失了。
我的问题是:
我打算调用
message_t (size_t)
构造函数。为什么会尝试在机器 B 上使用私有的message_t (const message_t&)
?使错误消失的代码更改删除了赋值运算符。为什么编译器不抱怨
void operator = (const message_t&)
是私有的,而是抱怨message_t (const message_t&)
?为什么机器A上没有错误,虽然
message_t (const message_t&)
在那里也是私有的?我想这与声明message_t (size_t)
explicit
有关,但我不明白这个关键字的作用。 (edit: 原来我不知道A机版本有move构造函数,B机版本没有。)
转
auto zm = zmq::message_t {serialized.size()};
进入
izmq::message_t zm {serialized.size()};
因为 = 调用(不需要的,私有的)复制构造函数
正在关注
auto zm = zmq::message_t {serialized.size()};
不是作业,
但是使用移动或复制构造函数(可能被省略)初始化 zm
应该可以访问(即使它被省略)。
如预期的那样explicit message_t (size_t)
构建了临时文件。
我怀疑 Clang++ 版本 3.4.2-13 中存在错误,因为您应该遇到与机器 B 中相同的错误。(A 中 B 没有的移动运算符解释这种行为)。
auto zm = zmq::message_t {serialized.size()};
是一个变量声明,所以在这种情况下 = 是一个复制初始化而不是矫揉造作,这就是为什么这是被调用的构造函数而不是矫揉造作的运算符。
显式关键字意味着构造函数仅被考虑用于直接初始化,
zmq::message_t zmq {serialized.size()};
您可以在此处找到更多详细信息和示例:http://en.cppreference.com/w/cpp/language/explicit