提升不可复制的怪异
Boost non-copyable weirdness
我有一个继承自boost::noncopyable
的类;比如说,标题摘录如下:
class A : boost::noncopyable {
...
blah
...
private:
struct impl;
boost::scoped_ptr<impl> m_impl;
};
然后在我的解决方案的一个项目中,我有一个类(也恰好继承自boost::noncopyable
),一个在实现细节中的私有成员是对类型 A 的引用,例如,在标头摘录中:
class B : boost::noncopyable {
...
blah
...
private:
struct impl;
boost::scoped_ptr<impl> m_impl;
};
在实施摘录 (CPP) 中:
struct B::impl {
impl(A& a) : m_a(a) {}
set_A(A& a) {m_a = a;}
A& m_a;
...
}
B(A& a) : m_impl(new impl(a)) {}
...
然后在我的解决方案的另一个项目中,我有一个从 B 继承的类 C,比如说,带有标题摘录:
class C : public B {
...
blah;
...
private:
struct impl;
boost::scoped_ptr<impl> m_impl;
};
在实施摘录 (CPP) 中:
struct C::impl {
impl(A& a) : m_a(a) {}
void set_A(A& a) {m_a = a;}
A& m_a;
};
C(A &a) : B(a), m_impl(new impl(a)) {}
...
但是当我尝试在 MSVC++ 2008 中构建时,出现以下错误:
error C2248: 'boost::noncopyable_::noncopyable::operator =' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'
see declaration of 'boost::noncopyable_::noncopyable::operator ='
error C2248: 'boost::scoped_ptr<T>::operator =' : cannot access private member declared in class 'boost::scoped_ptr<T>' with T = A::impl
This diagnostic occurred in the compiler generated function 'A& A::operator =(const A&)'
编译器只有 C 的set_A
函数有问题,而不是 B 的set_A
。如果有人对此有任何想法并可以阐明一些信息,请表示感谢?一如既往地感谢您的关注。
编辑:
总而言之,我在这里不明白的是为什么编译器对何时应用有关boost::noncopyable
的错误很挑剔。当我注释掉类 C 中的set_A(..)
函数时,一切都编译正常。但是当我保留它时,它会给出错误,而在 B 类中它没有任何问题。我还稍微编辑了上面的错误消息以提供更多细节。我在这里注意到它陈述了一些关于编译器生成的函数的内容。难道由于某种原因,这种情况只发生在C类身上?为什么?
[编辑]
首先,现在我更好地理解了你的问题,但我仍然不明白你为什么不想将你的实现更改为:
struct C::impl {
impl(A& a) : m_a(&a) {}
void set_A(A& a) {m_a = &a;}
A* m_a;
};
对于不可复制A
,这将简单不起作用:
void set_A(A& a) {m_a = a;}
无论如何:
此错误:
错误 C2248:"提升::scoped_ptr::运算符 =":无法访问 在类 'boost::scoped_ptr' 中声明的私人成员,T = 答::impl
这是因为boost::scoped_ptr<T>
是不可复制的,这一事实与您的A
类不可复制的事实无关。
此错误:
此诊断发生在编译器生成的函数 'A& A::运算符 =(const A&)'
肯定是因为XXX::set_A(A& a) { m_A = a; }
功能之一。在这样的函数中,A::operator =(const A&)
是必需的 - 并且因为它没有定义编译器,所以尝试定义默认的编译器。默认情况下,一个成员将一个接一个地复制成员 - 其中一个成员A
不可复制boost::scoped_ptr<A::impl>
。
那么对您来说最重要的问题 - 为什么只有一个错误 - 而不是两种XXX::set_A(A& a) { m_A = a; }
方法?
我在我的 g++ 4.5.x 环境中测试了您的案例的简化版本。诊断与您的诊断非常相似 - 效果非常相似 - 只有一个set_A
功能被投诉 - 第一个。这是因为两者都需要A& operator = (const A&)
- 但只为第一个生成。G++给出了出色的诊断:
../src/AnExample.cpp:24:32: note: synthesized method 'A& A::operator=(const A&)' first required here
我的例子和诊断:
class noncopyable {
private:
noncopyable(const noncopyable&);
noncopyable& operator = (const noncopyable&);
};
class A {
noncopyable m;
};
class B {
B(A& a) : a(a) {}
void set_A(A& a) { this->a = a; } // line 24
A& a;
};
class C {
C(A& a) : a(a) {}
void set_A(A& a) { this->a = a; }
A& a;
};
make all
Building file: ../src/AnExample.cpp
Invoking: Cygwin C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/AnExample.d" -MT"src/AnExample.d" -o "src/AnExample.o" "../src/AnExample.cpp"
../src/AnExample.cpp: In member function 'A& A::operator=(const A&)':
../src/AnExample.cpp:15:17: error: 'noncopyable& noncopyable::operator=(const noncopyable&)' is private
../src/AnExample.cpp:18:9: error: within this context
../src/AnExample.cpp: In member function 'void B::set_A(A&)':
../src/AnExample.cpp:24:32: note: synthesized method 'A& A::operator=(const A&)' first required here
make: *** [src/AnExample.o] Error 1
src/subdir.mk:18: recipe for target `src/AnExample.o' failed
- 简单可复制与可简单复制
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 对于参加可复制和可移动类的访问者来说,应该有多少过载?
- 可变参数宏:无法通过"..."传递非平凡可复制类型的对象
- 为什么 std::atomic<std::string> 会给出微不足道的可复制错误?
- 我可以隐式地创建一个琐碎的可复制类型吗
- 是std::memcpy在不同的可复制类型之间的未定义行为
- 为什么一对常量是微不足道的可复制的,而对不是?
- 在一个微不足道的可复制结构中,移动语义应该实现吗?
- 防止作用域枚举可复制/可移动
- C :对象上的可复制视图
- 防御性地应用 std::move 到平凡可复制的类型是否不可取
- 为什么 std::function 本身是可复制构造的类型?
- C++不可复制的 lambda 的行为是可复制的
- 错误:无法通过'...'传递非平凡可复制类型的对象'class boost::filesystem::path'
- 不能让类是微不足道的可复制的。我做错了什么?
- 使用临时存储区复制普通的可复制类型:允许吗
- 使用realloc可以安全地重新分配琐碎的可复制对象的存储吗
- 为什么Boost.Asio处理程序必须是可复制的
- 我需要可复制的缓冲区,尽可能轻(例如,不初始化零)