tags:

views:

144

answers:

3

Hi there!

Given the following code:

#include <boost/noncopyable.hpp>

enum Error { ERR_OK=0 };

struct Filter : private boost::noncopyable
{
  Filter() {}
  virtual ~Filter() {}

  virtual int filter(int* data) const = 0;

};

struct  SpecialFilter : public Filter, private boost::noncopyable
{
  inline SpecialFilter(unsigned int min, unsigned int max) : min(min), max(max) {}
  virtual ~SpecialFilter() {}

  virtual int filter(int* data) const
  {
    // ...
    return ERR_OK;
  }

  unsigned int min;
  unsigned int max;
};

struct AClass
{
  AClass() {}
  AClass(const AClass& other) {}
  ~AClass() {}

  int specialFilter(int channel, int minThreshold, int maxThreshold)
  {
    // ...
    return filter(channel, SpecialFilter(123, 321));
  }

  int filter(int channel, const Filter& filter)
  {
    // ...
    return ERR_OK;
  }

};

My compiler (gcc 4.2 brought by Xcode on Mac OS X Snow Leopard) complains:

- warning: direct base ‘boost::noncopyable_::noncopyable’ inaccessible in ‘SpecialFilter’ due to ambiguity
- noncopyable.hpp: In copy constructor ‘Filter::Filter(const Filter&)’:
- noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
- synthezised method first required here: [return filter(channel, SpecialFilter(123, 321));]

But I don't call the copy constructor!

Please excuse my poor English.

Thanks for help, Niels

+1  A: 

Firstly, remove the private derivation from SpecialFilter - it is not necessary, as Filter is already not copyable. Problems like this are why I think solutions like boost::non_copyable are a bad idea - there are simpler ways of saying you don't want copies.

Secondly, though I'm not sure this is your problem, C++ says that a public copy constructor must be available to the compiler under several circimstances, even if the compiler does not actually use it.

anon
+8  A: 

You never call copy constructor. The copy constructor is always called for you implicitly by the compiler. So you need to learn to recognize situations when it might be called.

When you attach a const reference to a temporary object

...
return filter(channel, SpecialFilter(123, 321));
...

the compiler has the right to perform a copy of the temporary object and require an accessible copy constructor (even if it won't be actually called). This is what is causing the problem in your case.

In other words, when you make some type non-copyable, you also give up the possibility to attach const references to temporary objects of that type.

AndreyT
Thanks. I learned something new ...
Polybos
A: 

Remember when you pass object and return object by value --> copy constructor is invoked.

Ashish