- Placement new, alignment, and struct with pointer to POD - 1 Update
- Dependecy Injection - 7 Updates
- Core language basic types support - 1 Update
- Does the function below show undefined behavior? - 2 Updates
Daniel <danielaparker@gmail.com>: Dec 12 09:09AM -0800 I'm trying to understand the rules for alignment with placement new. If we have struct A { size_t length; }; my understanding (please correct me if I'm wrong) is that this results in a data structure that is properly aligned: typedef typename std::aligned_storage<sizeof(A), alignof(A)>::type storage_type; char* storage = new char [sizeof(storage_type)]; A* pa = new(storage)A(); But what if we have struct B { size_t length; int *p; }; and wish to allocate storage for B and p with placement new from the same storage? Does this satisfy alignment rules? typedef typename std::aligned_storage<sizeof(B), alignof(B)>::type storage_type; size_t length = 10; char* storage = new char [sizeof(storage_type)+length*sizeof(int)]; B* pb = new(storage)B(); pb->p = new(storage + sizeof(storage_type))int[length]; Thanks, Daniel |
"Öö Tiib" <ootiib@hot.ee>: Dec 11 06:01PM -0800 On Saturday, 12 December 2015 01:13:29 UTC+2, Chris Vine wrote: > Static polymorphism requires you to propagate types. That is not what > is normally intended with dependency injection. But no one owns the > expression so it can mean whatever you want it to mean. I thought what was intended with dependency injection was to depend on abstractions (loose coupling) not to depend on concrete types (tight coupling). So if statically passed type conforms to needed abstraction (or concept) then what was intended has been achieved. It is even better for programmer if nothing was needed to be passed since statically defaulted type does already what is needed. > > policies. The .NET gang typically injects interface pointers. > Which is what is normally meant by dependency injection (or the C++ or > Java or ... equivalent). Abstract interface and dynamically polymorphic pointers are one way to achieve abstraction. In C++ we never limit ourselves to single way because we want our programs to work as simple way as possible and ourselves to express it as simple way as possible. However never simpler than possible so sometimes we also need dynamic polymorphism in C++ too. > all the time. They are perhaps closer to the command pattern but all > these (strategy pattern, command pattern, policy pattern, dependency > injection) are related and serve similar ends. Principles are important. There are no silver bullet "normal" techniques to follow those principles. Most important principle is KISS. Lot of dynamically polymorphic interfaces can cause explosion of types, complexity shifting into relations between classes and that may cause difficulties to trace behaviors. Result may easily become hard to handle without tools that the OP asked for or even with those. ;) |
"Tobias Müller" <troplin@bluewin.ch>: Dec 12 07:55AM >> I see no big difference except the increased verbosity of templates. > Resulting in the template keyword spreading like a virus in your code > with a proportional increase in compilation time and binary file size. If you want static polymorphism everywhere then yes, that's the price to pay. Compilation will increase for sure, binary size depends. In practice you probably won't have too many different instantiations and with better optimization possibilities size could probably even decrease. > The big difference is having dependencies on abstractions rather than > concretions results in looser coupling and better design sausages. Nothing prevents you from still having an IBar interface. Bar beeing a template itself is orthogonal to that. I'm not saying that runtime polymorphism is generally bad and templates should always be preferred. But if you need the performance it's a valid alternative for achieving DI. Tobi |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Dec 12 10:58AM On Fri, 11 Dec 2015 18:01:44 -0800 (PST) > (or concept) then what was intended has been achieved. It is even > better for programmer if nothing was needed to be passed since > statically defaulted type does already what is needed. I think we are in danger of talking across each other and losing the point, whilst agreeing. It's purpose is loose coupling by externalizing or delegating the required behaviour to the injector (aka dependency inversion). The service object supplying the dependency will of necessity be concrete, but will be owned by the client polymorphically in some fashion (it does not know or care how its dependency is implemented). This might involve the service object being passed as an interface/ABC, but that is an implementation detail; it could equally well be held by a polymorphic function object in the signal/slot style. I don't think either of us disagree with that. Furthermore static polymorphism requires you to propagate the polymorphic behaviour via types. I don't think either of us disagree with that either. That causes a multiplication of types and therefore of templates. In its purest form DI does not provide defaults: the user is expected to provide the service objects on configuration. But if you want a default, that is orthogonal to whether you use static or dynamic polymorphism. None of this is particularly new. We have been doing it for years. As someone else has mentioned, what is new(ish) is the availability of frameworks to manage the explosion of dependency complexity the technique can cause. Chris |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Dec 12 03:40PM On 12/12/2015 07:55, Tobias Müller wrote: > I'm not saying that runtime polymorphism is generally bad and templates > should always be preferred. But if you need the performance it's a valid > alternative for achieving DI. It isn't proper DI though as it involves dependencies on concretions rather than on abstractions sausages. /Flibble |
"Tobias Müller" <troplin@bluewin.ch>: Dec 12 04:03PM >> alternative for achieving DI. > It isn't proper DI though as it involves dependencies on concretions > rather than on abstractions sausages. I think I've lost you. I don't see any concretions. Tobi |
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Dec 12 04:37PM On 12/12/2015 16:03, Tobias Müller wrote: >> It isn't proper DI though as it involves dependencies on concretions >> rather than on abstractions sausages. > I think I've lost you. I don't see any concretions. The template parameters are concrete rather than abstract types sausages. /Flibble |
"Öö Tiib" <ootiib@hot.ee>: Dec 12 08:49AM -0800 On Saturday, 12 December 2015 12:58:27 UTC+2, Chris Vine wrote: > > statically defaulted type does already what is needed. > I think we are in danger of talking across each other and losing the > point, whilst agreeing. That is possibility. > interface/ABC, but that is an implementation detail; it could equally > well be held by a polymorphic function object in the signal/slot > style. I don't think either of us disagree with that. Yes. There is at least one more style of dynamic polymorphism (a "variant"). It is quite widely used for compacting data but not for inverting dependencies. > polymorphic behaviour via types. I don't think either of us disagree > with that either. That causes a multiplication of types and therefore > of templates. How it causes multiplication of templates? What is bad about templates? For me templates cause relations that are already known compile time to be fixed. For programmer it is way to "favor immutability" for compiler it is opportunity to diagnose issues early and to optimize. Introducing dynamic polymorphism where unneeded is worse than avioiding 'const' keyword. > to provide the service objects on configuration. But if you want a > default, that is orthogonal to whether you use static or dynamic > polymorphism. The issue of defaults is orthogonal in theory but actual in practice. The difference is that dynamically polymorphic defaults must be ready made and available even when not used by particular module. That means run-time paying for something that is not used. Unless such default is something extremely cheap and trivial it is not made. > someone else has mentioned, what is new(ish) is the availability of > frameworks to manage the explosion of dependency complexity the > technique can cause. Right. Doing that in correct way for C++ by taking into account what objects or relations are immutable and what are not is slightly more difficult than in languages where everything is pointer to object whose every method is virtual. However the outcome will keep beating others 4:1 and after all ... that is all that matters. ;) |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Dec 12 03:23PM +0100 On 12/10/2015 2:49 PM, Alf P. Steinbach wrote: >[snip] This header has now evolved a little. • Due to David Brown's commentary I realized that the "wrap_to" function did not do anything that proper suppression of sillywarnings didn't do, so, removed -- it was not a proper way to suppress that sillywarning (I wonder about the process in Microsoft that causes them to introduce ever more and ever more misleading sillywarnings for Visual C++, hmf). • For consistency and for more expressive readable code, and to mirror the template meta-programming boolean operations (hm, it would be nice with OPERATORS for types!), I added functions "exactly_one_of" (xor), "all_of" (and), "not_all_of" (nand), "any_of" (or) and "none_of" (nor). • With improved template "Type_set_" I could simplify the type set expressions. Interesting tidbit: just small typos in the code for "Type_set_" caused Visual C++ to near-crash, unable to recover from the errors, and telling me that I would be asked to report this to Microsoft. Not an ICE, but evidently not-by-design behavior. That's apparently new with Visual C++ 2015. Never seen it before, and I've reported a host of internal compiler errors for Visual C++. <code> #pragma once // core_language_support/basic_types.hpp // Copyright © Alf P. Steinbach 2015. Boost Software License 1.0. #include <p/cppx/core_language_support/type_builders.hpp> // cppx::Ref_ #include <p/cppx/core_language_support/basic_type_aliases.hpp> // cppx::(Byte, Size) #include <p/cppx/tmp/Type_set_.hpp> // cppx::Type_set_ #include <p/cppx/tmp/sfinae.hpp> // cppx::If_ #include <p/cppx/macros/platform_sniffing.hpp> // CPPX_PLATFORM* #include <p/cppx/macros/CPPX_STATIC_ASSERT.hpp> // CPPX_STATIC_ASSERT #include <type_traits> // std::conditional_t // For a discussion of Syschar see the article "Portable String Literals in C++" by // Alf P. Steinbach, ACCU Overload journal August 2013; the article is available online // at <url: http://accu.org/index.php/journals/1842>. Eessentially it's the natural // Unicode character endcoding unit for the system at hand, strictly typed as an enum. // As an enum it's compatible with std::basic_string short buffer optimization. #ifndef CPPX_SYSCHAR_BITSIZE # if defined( CPPX_PLATFORM_IS_WINDOWS ) # define CPPX_SYSCHAR_BITSIZE 16 // Implies UTF-16 encoding & wchar_t. # elif defined( CPPX_PLATFORM_IS_UNIXLAND ) # define CPPX_SYSCHAR_BITSIZE 8 // Implies UTF-8 encoding & char. # else # define CPPX_SYSCHAR_BITSIZE 0 // Will use wchar_t as a default. # endif
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment