I have a class (let's call it base
for the moment) that has a protected interface, including protected constructors etc. Some functions of base
return an instance of base
by value:
class base {
protected:
base() {}
base (base const &other) {} // line 6
base foo () {
base ret;
return ret;
}
};
These functions are wrapped in the derived classes to return the derived type like so:
class derived : public base {
private:
derived(base const &b) : base(b) {}
public:
derived() : base() {}
derived foo() {
derived d(base::foo()); // line 21
return d;
}
};
To facilitate the conversion from the base
return type into a derived
return type, I provide a private constructor in derived
that handles this.
Compiling this on Centos 5.8 with gcc 4.1.2 produces the following error:
test.cpp: In member function ‘derived derived::foo()’:
test.cpp:6: error: ‘base::base(const base&)’ is protected
test.cpp:21: error: within this context
With gcc 4.6.1 and clang 2.9 on Linux Mint 12, the code compiles file, even with -Wall -Wextra
, apart from an unused parameter
warning for base
's copy constructor.
I think this could be a compiler bug in gcc 4.1.2, but I was unable to find anything on the net. Has anyone seen this before?
I cannot update the compiler without massive pain. Is there a simple workaround other than making the copy constructor of the base class public?
EDIT I added base b;
before line 21 in derived::foo()
. In that case, gcc 4.6.1 and gcc 4.1.2 complain that the default ctor of base
is protected, clang 2.9 compiles without warning. This is what David Rodríguez - dribeas said in his comment - the default ctor cannot be called on a different instance of base
.
EDIT 2 The standard paragraph that seems to apply here is 11.5 [class.protected]. gcc 4.1.2 seems to be correct in refusing my code as incorrect and I wonder why gcc 4.6.1 and clang allow it. See my own answer for a preliminary solution.
A workaround that you could try would involve creating a private constructor for derived that constructs it's base by calling the base function:
class derived : base {
struct from_base_foo {};
derived( from_base_foo ) : base( base::foo() ) {}
public;
derived foo() {
return derived( from_base_foo() );
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With