【问题标题】:Boost non-copyable weirdness增强不可复制的怪异
【发布时间】:2012-09-12 09:25:33
【问题描述】:

我有一个继承自 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成员是A&amp;类型,即引用,而不仅仅是A
  • 是的.. 这对我的实施至关重要。
  • 也许这是一个编译器错误?仅给定 AB 定义,clang 和 GCC 都不会编译它 - 它们都(正确地)在 B::set_A 中出错(因为 A 的赋值运算符是私有的)。

标签: c++ visual-studio-2008 boost noncopyable


【解决方案1】:

[编辑]

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

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:'boost::scoped_ptr::operator =':无法访问 使用 T = 在类 'boost::scoped_ptr' 中声明的私有成员 A::实现

是因为boost::scoped_ptr&lt;T&gt; 是不可复制的,这一事实与您的A 类不可复制这一事实无关。

这个错误:

此诊断发生在编译器生成的函数'A& A::operator =(const A&)'

肯定是因为XXX::set_A(A&amp; a) { m_A = a; } 函数之一。在这样的函数中 A::operator =(const A&amp;) 是必需的 - 因为它没有定义编译器尝试定义默认的。默认一个将一个一个地复制成员 - A 成员之一是不可复制的 boost::scoped_ptr&lt;A::impl&gt;

那么对您来说最重要的问题 - 为什么只有一个错误 - 而不是两个 XXX::set_A(A&amp; a) { m_A = a; } 方法?

我在我的 g++ 4.5.x 环境中测试了您的案例的简化版本。诊断与您的非常相似 - 效果也非常相似 - 仅抱怨一个 set_A 函数 - 第一个。 这是因为两者都需要A&amp; operator = (const A&amp;) - 但只为第一个生成。 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

【讨论】:

  • 感谢您的宝贵回复。我同意你的 cmets,不,我不会混淆参考的使用。但是,您的帖子并没有完全回答我关于为什么编译器错误只出现在第二个类的 set 函数中的具体问题?我原以为它会在两个地方都抛出编译器错误,但是我定义了 B 类的 VC++ 2008 项目编译得很好!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多