Re: [boost] boost::final similar to boost::noncopyable

Ok, good to know that, but, I'm still curious what is wrong with my code. Why is it passing a compiler and why is failing on the other? "Gennadiy Rozental" <gennadiy.rozental@thomson.com> wrote in message news:f3hcjq$4i6$1@sea.gmane.org...
AFAIK there is no standard compliant way to implement final. At least not until C++09.
Gennadiy

At Boost Vault there a few packages which implement the final concept. Indeed, there is boost::noninheritable which uses a technique closer to yours. Also, I wrote some times ago an experimental library, boost::nonderivable, which uses a different approach but it is experimental (as I said), thus it shouldn't used in serious works....until, I have time (and technical capabilities) to review my code. Best Regards, Manuel Fiorelli www.fioreltech.net

Hi Manuel,
At Boost Vault there a few packages which implement the final concept. Indeed, there is boost::noninheritable which uses a technique closer to
I tested the code boost::noninheritable made by Vladislav Lazarenko, it has exactly the same problem, in VC7.1 and VC8 following code: class UniquePerson : public boost::noninheritable<UniquePerson> { public: UniquePerson() {} ~UniquePerson() {} }; int main() { UniquePerson a; UniquePerson b(a);//ERROR here } So it is not too much of a help.
Also, I wrote some times ago an experimental library, boost::nonderivable, which uses a different approach
I would be interested in your technique, of course, if you like to share it. I tried to search the Vault for other final, but did not got to lucky. Do you think there is any which may be interesting to be checked? Best regards, Costin Calisov ----- Original Message ----- From: "Manuel Fiorelli" <manuel.fiorelli@gmail.com> To: <boost@lists.boost.org> Sent: Tuesday, May 29, 2007 7:00 PM Subject: Re: [boost] boost::final similar to boost::noncopyable
At Boost Vault there a few packages which implement the final concept. Indeed, there is boost::noninheritable which uses a technique closer to yours. Also, I wrote some times ago an experimental library, boost::nonderivable, which uses a different approach but it is experimental (as I said), thus it shouldn't used in serious works....until, I have time (and technical capabilities) to review my code.
Best Regards, Manuel Fiorelli www.fioreltech.net _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Costin Calisov wrote:
Ok, good to know that, but, I'm still curious what is wrong with my code. Why is it passing a compiler and why is failing on the other?
Probably just a choice of internal compiler design... The following appears to work on MSVC: class final_base { protected: final_base(); }; class final : public virtual final_base { protected: final(); private: final(const final&); }; Notice that I used protected construction and specified a private copy constructor for final. The latter gets around's MSVC error re: no copy constructor or explicit copy constructor. It seems that MSVC compiler is implicitly defining an explicit copy constructor so you have to declare one to get around it. The former lets you use final without having to remember to inherit from it protected/private: class B : final { public: B() {} }; class C : B { public: C() {} // Error - no derive from the B but msg is not obvious IMHO }; int main() { B t1; B t2(t1); // Okay - because of private copy constructor in final } HTH, -Chris

----- Original Message ----- From: "Christopher Woods" <cwoods_eol@yahoo.com> To: <boost@lists.boost.org> Sent: Tuesday, May 29, 2007 7:49 PM Subject: Re: [boost] boost::final similar to boost::noncopyable
The latter gets around's MSVC error re: no copy constructor or explicit copy constructor. It seems that MSVC compiler is implicitly defining an explicit copy constructor so you have to declare one to get around it.
Hi Chris, I was hopping also, but I must do something wrong, I copy paste your code in VC71, and VC8 and get the same error with no copy constructor ...following is the full code I used: class final_base { protected: final_base(); }; class final : public virtual final_base { protected: final(); private: final(const final&); }; class B : final { public: B() {} }; /*class C : B { public: C() {} // Error - no derive from the B but msg is not obvious IMHO };*/ int main() { B t1; B t2(t1); // Okay - because of private copy constructor in final } Best Regards, Costin Calisov

Costin Calisov wrote:
I was hopping also, but I must do something wrong, I copy paste your code in VC71, and VC8 and get the same error with no copy constructor ...following is the full code I used:
No - you didn't do anything wrong. Sorry for the bump steer there. I thought that I had it working correctly but I jumped the gun apparently on 2 different things... The only thing that I can think of is that because of the virtual keyword MS is assuming that there is multiple inheritance going on and therefore opting to not attempt to provide a default copy constructor - as what is the correct copy path for A's values in the classic diamond inheritance example? class A class B : virtual A [class C : virtual A] class D : B[, C] I'm guessing that GCC on the other hand is able to realize that this is still in fact a single inheritance case that you are attempting to implement (virtual not withstanding) and can therefore correctly imply the copy constructor. class A class B : virtual A class D : B So let's try a modified round #1 approach for MSVC: class final_base { protected: final_base() {} }; class final : public virtual final_base { protected: final() {} }; class B : final { public: B() {} B(const B&) { /* MS Compiler requires we provide copy constructor when virtual is used in the inheritance chain. */ } }; class C : B { public: C() {} // Error: Can't derive but unclear error msg IMHO }; int main() { B t1; B t2(t1); } Alternative (round #2) - if you don't want to have to specify a copy constructor then you'll have to make a tradeoff in the class declaration: class final2 { protected: final2() {} }; class D : virtual final2 /* Not as clean IMHO as you must remember to use 'virtual' or all is lost */ { public: D() {} }; class E : D { public: E() {} // Error: Can't derive but msg unclear IMHO }; int main() { D t1; D t2(t1); } Personally, I think I'd rather go with the modified round #1 approach and write a copy constructor for B. The round 2 approach requires that a class writer remember to use 'virtual final' because if they just used 'final' then you can still derive from it. Assuming that you agree with that assessment, then it becomes necessary for you to find a way to make GCC also baulk unless a copy constructor is provided with the B class (assuming you want some portability). Unfortunately I don't have GCC on my machines so I can't help you there - a protected or private copy constructor within final or final_base might make GCC complain... You'll have to experiment. HTH, -Chris

Great description of the issue. Now is all clear to me thank you a lot. I owe you a cold beer :) ----- Original Message ----- From: "Christopher Woods" <cwoods_eol@yahoo.com> To: <boost@lists.boost.org> Sent: Wednesday, May 30, 2007 6:13 PM Subject: Re: [boost] boost::final similar to boost::noncopyable
Costin Calisov wrote:
I was hopping also, but I must do something wrong, I copy paste your code in VC71, and VC8 and get the same error with no copy constructor ...following is the full code I used:
No - you didn't do anything wrong. Sorry for the bump steer there. I thought that I had it working correctly but I jumped the gun apparently on 2 different things...
The only thing that I can think of is that because of the virtual keyword MS is assuming that there is multiple inheritance going on and therefore opting to not attempt to provide a default copy constructor - as what is the correct copy path for A's values in the classic diamond inheritance example?
class A class B : virtual A [class C : virtual A] class D : B[, C]
I'm guessing that GCC on the other hand is able to realize that this is still in fact a single inheritance case that you are attempting to implement (virtual not withstanding) and can therefore correctly imply the copy constructor.
class A class B : virtual A class D : B
So let's try a modified round #1 approach for MSVC:
class final_base { protected: final_base() {} };
class final : public virtual final_base { protected: final() {} };
class B : final { public: B() {} B(const B&) { /* MS Compiler requires we provide copy constructor when virtual is used in the inheritance chain. */ } };
class C : B { public: C() {} // Error: Can't derive but unclear error msg IMHO };
int main() { B t1; B t2(t1); }
Alternative (round #2) - if you don't want to have to specify a copy constructor then you'll have to make a tradeoff in the class declaration:
class final2 { protected: final2() {} };
class D : virtual final2 /* Not as clean IMHO as you must remember to use 'virtual' or all is lost */ { public: D() {} };
class E : D { public: E() {} // Error: Can't derive but msg unclear IMHO };
int main() { D t1; D t2(t1); }
Personally, I think I'd rather go with the modified round #1 approach and write a copy constructor for B. The round 2 approach requires that a class writer remember to use 'virtual final' because if they just used 'final' then you can still derive from it.
Assuming that you agree with that assessment, then it becomes necessary for you to find a way to make GCC also baulk unless a copy constructor is provided with the B class (assuming you want some portability). Unfortunately I don't have GCC on my machines so I can't help you there - a protected or private copy constructor within final or final_base might make GCC complain... You'll have to experiment.
HTH,
-Chris
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

I agree with you that boost::noninheritable is probably stronger than boost::nonderivable (even if the proposed exploit is a very subtle one). I read boost::noninheritable documentation and I found a typo: indeed, in the section "When to use", you refer to your library as "boost::noncopyable". Also, I suggest you to: 1) list every known supported compiler, and especially you should compare it with boost officially supported platforms 2) add to the documentation a section where you explain how to solve the problem about "value semantics" (copy constructor and assignment operator) Best regards, Manuel Fiorelli www.fioreltech.net
participants (3)
-
Christopher Woods
-
Costin Calisov
-
Manuel Fiorelli