comp.lang.c++@googlegroups.com | Google Groups | ![]() |
Unsure why you received this message? You previously subscribed to digests from this group, but we haven't been sending them for a while. We fixed that, but if you don't want to get these messages, send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
- Correct vesion (Re: Clone an object with an abstract base class) - 17 Updates
- Assertion error on boost::unordered_set (and probably in stl unordered set). - 2 Updates
- Variadic Templates and aliases? - 5 Updates
- Unified Call Syntax - 1 Update
Paavo Helde <myfirstname@osa.pri.ee>: Oct 15 09:47PM -0500 >>> else if( typeid(*b).name() == typeid(D2).name() ) >>> b1 = new D2(*(reinterpret_cast<D2*>(b1))); >>> } You can compare directly typeid-s, no need to fetch out the names (besides, comparing names is not guaranteed to work, they can all be empty strings legally IIRC). >> to derived. > why not dynamic_cast? It would check if the conversion is valid, static > cast does not. Dynamic_cast is performed at runtime and can be quite slow. It would be silly to use dynamic_cast if you have just found out by comparing typeids that the conversion would be valid (maybe only in debug-build asserts, to verify you have not made a mistake in the code). A virtual clone function is still the best solution for the cloning problem: probably faster than the repeated if-else typeid check and also more scalable and maintainable. Cheers Paavo |
"Tobias Müller" <troplin@bluewin.ch>: Oct 16 06:08AM > bad from the users point of view seeing this kind of clone function which they never need? > But surely there is a way to hide the clone, like being protected, then > this would not be a problem. But clone is quite a fundamental function for polymorphic type hierarchies. I see no value in hiding that. Also covariant return types make it look much nicer: class Base { public: virtual Base* clone(); }; class Derived : public Base { virtual Derived* clone(); // instead of: // virtual Base* clone(); }; This is legal if the return type of the derived function is more specific than the one of the base function. (Which is always true in the case of "clone") Tobi |
JiiPee <no@notvalid.com>: Oct 16 07:14AM +0100 On 16/10/2014 03:47, Paavo Helde wrote: > You can compare directly typeid-s, no need to fetch out the names > (besides, comparing names is not guaranteed to work, they can all be > empty strings legally IIRC). sure > silly to use dynamic_cast if you have just found out by comparing typeids > that the conversion would be valid (maybe only in debug-build asserts, to > verify you have not made a mistake in the code). yes, did not notice that. Its like using vector [] instead of at() when we know the size of the vector. > A virtual clone function is still the best solution for the cloning > problem: probably faster than the repeated if-else typeid check and also > more scalable and maintainable. Why more scalable? typeid cannot handle all the cases? |
JiiPee <no@notvalid.com>: Oct 16 07:51AM +0100 On 12/10/2014 15:02, Paavo Helde wrote: > array of million strings, this would be a million wasted vtable pointers). > Cheers > P but I was just talking about a hypothetical situation if it was there. I do not think string::clone would be a good idea for string's public users, because if clone is needed in some rare cases it can be done for str just: string(str) |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 02:16AM -0500 >> problem: probably faster than the repeated if-else typeid check and >> also more scalable and maintainable. > Why more scalable? typeid cannot handle all the cases? First, adding a new class can be done in a single code place, no need to modify the common factory-style cloning function in the old code. Some shops demand multi-week QA testing if any old code is touched. Second, the new class can be added in a new dynamic load library which might not even had existed when the common function was written, so could not be handled by that. Even if it was written, there would appear problems with circular dependencies (new library should include headers for the old code, not vice versa). |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 02:21AM -0500 Paavo Helde <myfirstname@osa.pri.ee> wrote in > could not be handled by that. Even if it was written, there would > appear problems with circular dependencies (new library should include > headers for the old code, not vice versa). Oh, and third: typeid comparing has O(N) complexity in respect of the number of different classes, a virtual function call has O(1) complexity. Cheers Paavo |
JiiPee <no@notvalid.com>: Oct 16 08:46AM +0100 On 16/10/2014 08:16, Paavo Helde wrote: > not be handled by that. Even if it was written, there would appear problems > with circular dependencies (new library should include headers for the old > code, not vice versa). No just the wording "more scalable" which was confusing me. Isn't it better to say rather: "better scalable"? Because what you are talking about here is just that the virtual method is better manageable in the future....its not that the factory is not able to do the same things, its just that the virtual method is the better way to do it. Or are there situations where the factory is not able to do (with good or bad coding methods) the clones and it can *only* be done by the virtual method? That was my original question. If the same thing can be done with both methods (that we get the clone), then I would not say "is more scalable = more able to be changed in size (where the size is the ability to get clones)". |
JiiPee <no@notvalid.com>: Oct 16 08:52AM +0100 On 16/10/2014 08:16, Paavo Helde wrote: > not be handled by that. Even if it was written, there would appear problems > with circular dependencies (new library should include headers for the old > code, not vice versa). Can you show me a simple code example where the clone can only be done by virtual and not factory method? |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 11:24AM -0500 > No just the wording "more scalable" which was confusing me. Isn't it > better to say rather: "better scalable"? Sorry, not a native speaker - these terms seem the same to me. Cheers Paavo |
"Öö Tiib" <ootiib@hot.ee>: Oct 16 09:26AM -0700 On Thursday, 16 October 2014 10:52:40 UTC+3, JiiPee wrote: > > code, not vice versa). > Can you show me a simple code example where the clone can only be done > by virtual and not factory method? He wrote about modules. C++ does not have modules in its language description but that is a lie. In practice lot of applications (written in whatever programming languages) often use modules written in C++. Modules should not be tightly coupled with each other in all directions otherwise the whole point of having modules is lost and you have to link them all together everywhere. Imagine there is module where base class "Tool" is defined. Imagine it has also "ToolFactory". Now time passes and you need to develop module for certain application that needs a tool "Gallows". Result is dependency knot since "ToolFactory" needs to learn to clone "Gallows". Both modules need to be linked to all applications that deal with whatever "Tool"s. Crap design since "Gallows" are used rather rarely. That can be avoided if only "Gallows" know how to clone "Gallows". |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 11:53AM -0500 > Can you show me a simple code example where the clone can only be done > by virtual and not factory method? Here it goes. Assume that the build process checks out and builds projects one-by one, in the order specified somewhere else (I have used such a process for many years in the past), to avoid any fancy ideas of including b.h in the base library (which would by all wrong conceptually anyway). // base library (DLL) // a.h class A { public: virtual ~A() {} virtual A* clone() const = 0; }; void foo(A* x); // a.cpp void foo(A* x) { A* y = x->clone(); delete y; } // ------------------------------------- // extension library (DLL) - link to base library // b.h //#include <BaseLibrary/a.h> class B: public A { public: virtual B* clone() const override; }; // b.cpp B* B::clone() const { return new B(*this); } // ------------------------------------- // main program - link to base library and extension library // main.cpp //#include <BaseLibrary/a.h> //#include <Extensionlibrary/b.h> int main() { A* x = new B(); foo(x); delete x; } |
JiiPee <no@notvalid.com>: Oct 16 06:11PM +0100 On 16/10/2014 17:24, Paavo Helde wrote: > Sorry, not a native speaker - these terms seem the same to me. > Cheers > Paavo They have a bit different meaning. For example making more cars is different than making better cars. If two people make both 10 cars then its only a matter who made better cars. If the other one makes 10 cars and the other one 15 cars, then its a matter of who made better cars plus who made more cars. |
JiiPee <no@notvalid.com>: Oct 16 06:17PM +0100 On 16/10/2014 17:26, 嘱 Tiib wrote: > linked to all applications that deal with whatever "Tool"s. Crap design since > "Gallows" are used rather rarely. That can be avoided if only "Gallows" know > how to clone "Gallows". I do not disagree with virtual method being better. I am only saying that I cannot see that there would be a situation where the factory cannot produce the clone and only the virtual method can do it. But Paavo says he has an example (although there is no explanation), so I ll try to check that. |
JiiPee <no@notvalid.com>: Oct 16 06:20PM +0100 On 16/10/2014 17:53, Paavo Helde wrote: > such a process for many years in the past), to avoid any fancy ideas of > including b.h in the base library (which would by all wrong conceptually > anyway). and why factory system cannot do this? |
JiiPee <no@notvalid.com>: Oct 16 06:35PM +0100 On 16/10/2014 18:30, Martin Shobe wrote: > In casual conversation, either works fine. If I was being formal I'd > say, "... also scales and maintains better ..." > Martin Shobe more apples and better apples are a bit different to me :) ... that was the confusion I had. Do we have more apples, or not more but just better apples.... |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 12:38PM -0500 >> including b.h in the base library (which would by all wrong conceptually >> anyway). > and why factory system cannot do this? Well, how do you propose to do this? Maybe you could try to write a replacement for the foo() function which makes a copy of the passed object without using the virtual clone() function. |
Paavo Helde <myfirstname@osa.pri.ee>: Oct 16 12:42PM -0500 > its only a matter who made better cars. If the other one makes 10 cars > and the other one 15 cars, then its a matter of who made better cars > plus who made more cars. With cars I can see the difference! :) But not with "scalable", here I feel more==better. |
Evan Sebastian <evanlhoini@gmail.com>: Oct 16 09:28AM -0700 Hello, Have someone encountered the assertion error when working with boost unordered_set (and set)? The value type used is std::int64_t The assertion which fails is mlf >= minimum max load factor Which is the first statement in the function min_buckets_for_size in this header file. http://www.boost.org/doc/libs/1_50_0/boost/unordered/detail/table.hpp Details : I have two projects in Visual C++ 2013 (x86), one for library and one for native unit testing as per usual. In the project, there is a class that defines some resource When I changed one of its member's type from vector to unordered_set (and fixed the regression it caused until it builds fine), my unit testing project failed to run with this message (https://connect.microsoft.com/VisualStudio/feedback/details/786792/c-unit-testing-failed-to-set-up-the-execution-context-to-run-the-test). At first I used stl unordered set, so I tried changing to boost::unordered_set to see if that makes any difference. Then I get the assertion error. In the code itself, the said member only undergo 1. initialization via C++11 initializer list, 2. comparison, 3. insertion. The builds are fine, and the program executable doesn't show any unintended behavior. Unfortunately, I can't show the complete code since this is a private project. I would appreciate any help or suggestion on this problem. ------ Evan Sebastian |
"Öö Tiib" <ootiib@hot.ee>: Oct 16 10:12AM -0700 On Thursday, 16 October 2014 19:28:45 UTC+3, Evan Sebastian wrote: > Unfortunately, I can't show the complete code since this is a private project. Try to make minimal example that reproduces the issue. Constructing it typically reveals where the defect is in your private code. If it does not for you then at least you can post that thing since it is not complete code of your private project anymore. |
Robert Hutchings <rm.hutchings@gmail.com>: Oct 16 08:47AM -0500 I was given this code yesterday: #ifndef _MEMOIZE_H_ #define _MEMOIZE_H_ #include <tuple> #include <map> template < typename T > struct Memoize { template <typename... Args> static auto Func(Args... args) -> decltype(T::Func(std::forward<Args>(args)...)) { using INPUT = std::tuple<Args...>; using RESULT = decltype(T::Func(std::forward<Args>(args)...)); static std::map< INPUT, RESULT > repository; auto key = std::make_tuple(std::forward<Args>(args)...); auto it = repository.find(key); if (it != repository.end()) { return it->second; } else { auto result = T::Func(std::forward<Args>(args)...); repository[key] = result; return result; } } };
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment