提升不可复制的怪异感

squ*_*boo 5 c++ boost noncopyable visual-studio-2008

我有一个继承自的类boost::noncopyable; 比如,标题摘录如下:

class A : boost::noncopyable {
   ...
   blah
   ...
private:
   struct impl;
   boost::scoped_ptr<impl> m_impl;
};
Run Code Online (Sandbox Code Playgroud)

然后在我的解决方案的一个项目中,我有一个类(也恰好继承boost::noncopyable),一个实现细节中的私有成员是对类型A的对象的引用,比如在标题摘录中:

class B : boost::noncopyable {
   ...
   blah
   ...
private:
   struct impl;
   boost::scoped_ptr<impl> m_impl;
};
Run Code Online (Sandbox Code Playgroud)

并在实施摘录(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)) {}
...
Run Code Online (Sandbox Code Playgroud)

然后在我的解决方案的另一个项目中,我有一个继承自B的C类,比如带有标题摘录:

class C : public B {
   ...
   blah;
   ...
private: 
   struct impl;
   boost::scoped_ptr<impl> m_impl;
};
Run Code Online (Sandbox Code Playgroud)

并在实施摘录(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)) {}
...
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在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&)'
Run Code Online (Sandbox Code Playgroud)

编译器只有C set_A函数的问题,而不是B的问题set_A.感谢是否有人对此有任何想法并且可以解释一下?一如既往地感谢您的关注.

编辑:

总而言之,我在这里不明白的是编译器为什么要应用有关错误的挑剔boost::noncopyable.当我set_A(..)在C类中注释掉函数时,一切都编译好了.但是当我保留它时,它会给出错误,而它在B类中没有任何问题.我还略微编辑了上面的错误信息以提供更多细节.我在这里注意到它说明了编译器生成的函数.可能是因为某种原因这只发生在C级吗?为什么?

Pio*_*ycz 6

[编辑]

首先,现在我更好地理解你的问题,但我仍然不明白为什么你不想将你的实现改为:

struct C::impl {
    impl(A& a) : m_a(&a) {}
    void set_A(A& a) {m_a = &a;}
    A* m_a;
};
Run Code Online (Sandbox Code Playgroud)

使用A不可复制的这很简单,不起作用:

void set_A(A& a) {m_a = a;}
Run Code Online (Sandbox Code Playgroud)

无论如何:

这个错误:

错误C2248:'boost :: scoped_ptr :: operator =':无法使用T = A :: impl访问类'boost :: scoped_ptr'中声明的私有成员

因为boost::scoped_ptr<T>是不可复制的,这个事实与你的A类不可复制的事实无关.

这个错误:

此诊断发生在编译器生成的函数'A&A :: operator =(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
Run Code Online (Sandbox Code Playgroud)

我的例子和诊断:

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;
};
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)