Date: Sun, 19 Jul 2026 08:44:59 +0200
C++ moderators really don't like new keywords or constructions that make
life easier.
They make up template constructions to allow the new functionality or
existing C++ code to implement it in a a roundabout way.
That's probably the reason why C++ doesn't have things like:
- properties (get; set;)
- static constructors
Instead we get template additions like concepts that may have benefits
but probably doesn't appeal new developers. Or another type of string or
map.
It just gets too complicated to learn it at school, or as a first
computer language.
C++ is becoming the new Cobol.
On 2026-07-19 04:29, Lorand Szollosi wrote:
> Hi,
>
> First thing first: aren’t you ok with named ctor and movable types, because then it’s simpler.
>
> If not, even then: (something like this)
>
> #include <iostream>
> #include <utility>
>
> template<class Derived>
> class post_init_crtp {
> protected:
> class guard {
> friend class post_init_crtp;
>
> public:
> guard() = default;
>
> guard(const guard&) = delete;
> guard& operator=(const guard&) = delete;
>
> guard(guard&& other) noexcept
> : object_(std::exchange(other.object_, nullptr))
> {}
>
> ~guard() noexcept
> {
> if (object_)
> Derived::post_init(*object_);
> }
>
> private:
> Derived* object_ = nullptr;
> };
>
> explicit post_init_crtp(guard& g) noexcept
> {
> g.object_ = static_cast<Derived*>(this);
> }
> };
>
> class X final : private post_init_crtp<X> {
> friend class post_init_crtp<X>;
>
> int value_;
>
> static constexpr auto post_init = [](X& self) noexcept {
> std::cout << self.value_ << '\n';
> };
>
> public:
> X(guard guard = {})
> : post_init_crtp(guard)
> , value_(230)
> {}
> };
>
> int main()
> {
> X x;
> }
>
> This gives you the choice to call or not call the init later (some call that risk and slowdown when the `if' is not automatically replaced by the compiler). It works with non-final and descendants and other things as well.
>
> Also, in a purely theoretic case where we extended cpass to ctors (as described in cpass - uneval proposal) and you’re ok with CRTP, I can’t yet find a reason why it couldn’t be part of that syntax, something like:
>
> template<class T>
> struct post_init_crtp {
> post_init_crtp()
> {
> if constexpr (requires(T& object) { object.init(); }) {
> static_cast<T&>(*this).init();
> }
> }
> };
>
> class X : private cpass<post_init_crtp<X>> {
> public:
> virtual void init()
> {
> std::cout << "X\n";
> }
> };
>
> class XDerived final : public X {
> public:
> void init() override
> {
> std::cout << "XDerived\n";
> }
> };
>
>
> … because we’re talking about the same thing from different perspectives I think. You do it for ctors; I do it for ordinary functions, with a bit more genericity. E.g. in this version, you can have multiple kinds of aspects.
>
> Thanks,
> -lorro
>
>> On 5 Jul 2026, at 16:22, Ruud Rietvink via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> On 2026-07-05 15:01, Marcin Jaczewski wrote:
>>> niedz., 5 lip 2026 o 14:11 Ruud Rietvink <ruud_at_[hidden]> napisał(a):
>>>> 1) I don't suppress base class implementations, like constructors and
>>>> destructors they are all called.
>>> But I can suppress member initialization if type is trivial:
>>> ```
>>> struct Baz
>>> {
>>> int _data[10];
>>> Baz() // no zero init of `_data`
>>> {
>>> }
>>> Baz(int i) : _data{ i } // all data are set
>>> {
>>> }
>>> };
>>> ```
>> +class() has nothing to do with variabele initialization.
>>
>>>> 2) finalizers are independent of destructors, they are called in a
>>>> different line, before the destructor line.
>>>> You don't need one to have the other.
>>>> 3) Exception handling works the same as with destructors, also
>>>> independent of each other.
>>> You missed my point, adding this finizers make type not trivial and I
>>> do not think its good thing.
>>> At least you would need update every place in standard where they
>>> refer to not-trivial destructor and add "or finalizer".
>>>
>>> Similar case we have with `virtual` , what is the point of `virtual
>>> -Foo()` when you have normal `~Foo()`?
>>>
>>> Overall signature of the finalizer should be the same or at least
>>> compatible with one from the destructor.
>> Since finalizing() is separate from destruction(), they may differ in virtuality.
>>
>> -Foo() is independent of whatever ~Foo() does. And classes that use + or - are certainly not trivial.
>>
>>
>>>> 4) Propogation to member objects? I don't understand what you mean.
>>>>
>>> ```
>>> struct Foo
>>> {
>>> Bar _member;
>>> };
>>> ```
>>>
>>> We have both `-Foo()` and `-Bar()`. When and how `-Bar()` is called?
>>> Its called right before `~Foo()` or right before `~Bar()`? or called
>>> by `-Foo()`?
>>> You can think for case `std::optional<Bar>` too where `Bar` is not a
>>> direct member of optional.
>> The same order as with destruction:
>> First -Foo(), which calls -Bar() at the end, then ~Foo() that calls ~Bar() at the end
>>>>> On 2026-07-05 13:56, Marcin Jaczewski wrote:
>>>>>> I had somehow similar idea for "finalizers" but its was more "unwind" operators
>>>>>> that are called before dstructors is called.
>>>>>>
>>>>>> Main difference would be that different types of stack "unwinds" would
>>>>>> have its own functions
>>>>>> to make difference between exception unwinding and normal scope exit.
>>>>>> Or even cancellation of coroutines. Something would be useful for db
>>>>>> transact scope cancellation.
>>>>>>
>>>>>>
>>>>>> One thing I realized in my solution is that even in your case this new
>>>>>> `+foo()` and `-foo()` operators
>>>>>> need to have the same exception specification and triviality as the
>>>>>> constructor or destructor.
>>>>>> E.g. adding `-foo() noexcept(false) { throw 1; }` would change the
>>>>>> result of `noexcept(foo{})`.
>>>>>> This should be a hard error if the destructor does not have `noexcept(false)`.
>>>>>> This is needed to avoid unexpectedly changing behavior of other code
>>>>>> than need to know this things.
>>>>>>
>>>>>> Another thing to consider is how you control base functions of this
>>>>>> initializers and finishers functions?
>>>>>> How to suppress base class implementation?
>>>>>> How to propagate it to member objects? And who and when do that?
>>>>>> Is `virtual ` required on finalizers when you have a `virtual` destructor?
>>>>>>
>>>>>> niedz., 5 lip 2026 o 13:20 Ruud Rietvink via Std-Proposals
>>>>>> <std-proposals_at_[hidden]> napisał(a):
>>>>>>> C++ object initializer and finalizer
>>>>>>> ====================================
>>>>>>> Date: 2026-07-05
>>>>>>> Version: 0.1
>>>>>>> Author: Ruud Rietvink
>>>>>>>
>>>>>>>
>>>>>>> Problem
>>>>>>> -------
>>>>>>>
>>>>>>> In the constructor and destructor of an object you cannot use virtual
>>>>>>> methods properly.
>>>>>>> So calling a virtual method in a base class to get some possible derived
>>>>>>> value is not possible.
>>>>>>> During construction and destruction there is no guaranteed time that the
>>>>>>> object is fully constructed,
>>>>>>> so that virtuality covers all the layers of the object.
>>>>>>>
>>>>>>>
>>>>>>> Possible (partial) solutions
>>>>>>> ----------------------------
>>>>>>>
>>>>>>> 1) One solution is to call an initialize() method after construction,
>>>>>>> and a finalize() method directly before destruction.
>>>>>>> This is tedious and can easily be forgotten (exceptions, end of scopes).
>>>>>>>
>>>>>>> 2) The initialize() could be run automatically in a factory, calling
>>>>>>> initialize() in the factory create() method.
>>>>>>> You would have to force that the construction only takes place through
>>>>>>> this factory by a private/friend construction,
>>>>>>> or by adding a special factory tag to the constructor arguments.
>>>>>>> This doesn't solve the finalize() method though, nor copy
>>>>>>> construction/cloning.
>>>>>>>
>>>>>>> 3) With a RAII wrapper, you could call the initialize() method in the
>>>>>>> RAII constructor and the finalize()
>>>>>>> in the RAII destructor. Together with a special constructor tag you
>>>>>>> could force the RAII constructor to be used.
>>>>>>> This can be made generic. This does require more memory (pointer in RAII
>>>>>>> object).
>>>>>>> This fails for copy construction/cloning.
>>>>>>>
>>>>>>> 4) This could be done with templated inheritance.
>>>>>>> template <typename T> class LogWrapper : public T
>>>>>>> {
>>>>>>> public:
>>>>>>> template <typename... args>
>>>>>>> LogWrapper(T&&... args) : T(std::forward<Args>(args)...)
>>>>>>> {
>>>>>>> initializeLog();
>>>>>>> }
>>>>>>>
>>>>>>> ~LogWrapper()
>>>>>>> {
>>>>>>> finalizeLog();
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> Wrapping could be nested for different purposes
>>>>>>> (LogWrapper<XXXWrapper<Class>> object(....)).
>>>>>>> This fails when the class has clone() functionality (unless said API
>>>>>>> uses some standard copyable in the Wrapper).
>>>>>>>
>>>>>>>
>>>>>>> X) For all wrapper solutions the problem is that when you want to start
>>>>>>> or stop using it, or extend it, it is a lot of
>>>>>>> coding effort.
>>>>>>>
>>>>>>>
>>>>>>> Proposal
>>>>>>> --------
>>>>>>>
>>>>>>> Proposal is to introduce an initializer method that is automatically
>>>>>>> called after the construction is complete,
>>>>>>> and a finalizer method that is automatically called before the
>>>>>>> destruction of an object.
>>>>>>> Because the finalizer is called before the destructing, the vtable is
>>>>>>> still correct and virtual calling will work correctly.
>>>>>>> Proposed names:
>>>>>>> class::+class() for initializing
>>>>>>> class::-class() for finalizing
>>>>>>>
>>>>>>> Initializer is also called after copy construction.
>>>>>>>
>>>>>>> Example:
>>>>>>> class LogBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> virtual ~LogBase() = default;
>>>>>>> ...
>>>>>>> virtual const char* const logName() = 0; // or c++26-reflection
>>>>>>>
>>>>>>> +LogBase() { logStart(logName()); }
>>>>>>> virtual -LogBase() { logEnd(logName()); }
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> class EngineBase: protected LogBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> ~EngineBase() override = default;
>>>>>>> ...
>>>>>>> virtual EngineType engineType() = 0;
>>>>>>> +EngineBase() { addToEngine(engineType()); } //
>>>>>>> Optional, otherwise default
>>>>>>> -EngineBase() override { removeFromEngine } // Optional
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>> class Derived: protected EngineBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> ...
>>>>>>> EngineType engineType() override { return
>>>>>>> EngineType.Something; }
>>>>>>> const char* const logName() override { return "Derived Something"; }
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> EngineBase* base = new Derived();
>>>>>>> ...
>>>>>>> delete base;
>>>>>>>
>>>>>>>
>>>>>>> // Order:
>>>>>>>
>>>>>>> // LogBase()
>>>>>>> // EngineBase()
>>>>>>> // Derived()
>>>>>>> // Object intact.
>>>>>>> // +LogBase() (same order as constructor chain)
>>>>>>> // +EngineBase()
>>>>>>> // +Derived() (if any)
>>>>>>> // Life...
>>>>>>> // -Derived() (if any, same order as destructor chain, for all
>>>>>>> implementations of -class())
>>>>>>> // -EngineBase()
>>>>>>> // -LogBase()
>>>>>>> // Object still intact.
>>>>>>> // ~Derived()
>>>>>>> // ~EngineBase()
>>>>>>> // ~LogBase()
>>>>>>>
>>>>>>>
>>>>>>> Advantages
>>>>>>> ----------
>>>>>>>
>>>>>>> a) Easy to implement for compilers.
>>>>>>> b) Easy to optimize away for compilers, if not needed.
>>>>>>> c) No clashing new keywords.
>>>>>>> d) Completely optional and backwards compatible.
>>>>>>> e) If not used, not in the way.
>>>>>>> f) Could start a new paradigm: construct in (), initialize in +(),
>>>>>>> finalize in -(), destruct in ~().
>>>>>>> Also a lot of construction is moved to header file, these days.
>>>>>>> Also substitutes often used init() method when multiple
>>>>>>> constructors are present.
>>>>>>> --
>>>>>>> Std-Proposals mailing list
>>>>>>> Std-Proposals_at_[hidden]
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
life easier.
They make up template constructions to allow the new functionality or
existing C++ code to implement it in a a roundabout way.
That's probably the reason why C++ doesn't have things like:
- properties (get; set;)
- static constructors
Instead we get template additions like concepts that may have benefits
but probably doesn't appeal new developers. Or another type of string or
map.
It just gets too complicated to learn it at school, or as a first
computer language.
C++ is becoming the new Cobol.
On 2026-07-19 04:29, Lorand Szollosi wrote:
> Hi,
>
> First thing first: aren’t you ok with named ctor and movable types, because then it’s simpler.
>
> If not, even then: (something like this)
>
> #include <iostream>
> #include <utility>
>
> template<class Derived>
> class post_init_crtp {
> protected:
> class guard {
> friend class post_init_crtp;
>
> public:
> guard() = default;
>
> guard(const guard&) = delete;
> guard& operator=(const guard&) = delete;
>
> guard(guard&& other) noexcept
> : object_(std::exchange(other.object_, nullptr))
> {}
>
> ~guard() noexcept
> {
> if (object_)
> Derived::post_init(*object_);
> }
>
> private:
> Derived* object_ = nullptr;
> };
>
> explicit post_init_crtp(guard& g) noexcept
> {
> g.object_ = static_cast<Derived*>(this);
> }
> };
>
> class X final : private post_init_crtp<X> {
> friend class post_init_crtp<X>;
>
> int value_;
>
> static constexpr auto post_init = [](X& self) noexcept {
> std::cout << self.value_ << '\n';
> };
>
> public:
> X(guard guard = {})
> : post_init_crtp(guard)
> , value_(230)
> {}
> };
>
> int main()
> {
> X x;
> }
>
> This gives you the choice to call or not call the init later (some call that risk and slowdown when the `if' is not automatically replaced by the compiler). It works with non-final and descendants and other things as well.
>
> Also, in a purely theoretic case where we extended cpass to ctors (as described in cpass - uneval proposal) and you’re ok with CRTP, I can’t yet find a reason why it couldn’t be part of that syntax, something like:
>
> template<class T>
> struct post_init_crtp {
> post_init_crtp()
> {
> if constexpr (requires(T& object) { object.init(); }) {
> static_cast<T&>(*this).init();
> }
> }
> };
>
> class X : private cpass<post_init_crtp<X>> {
> public:
> virtual void init()
> {
> std::cout << "X\n";
> }
> };
>
> class XDerived final : public X {
> public:
> void init() override
> {
> std::cout << "XDerived\n";
> }
> };
>
>
> … because we’re talking about the same thing from different perspectives I think. You do it for ctors; I do it for ordinary functions, with a bit more genericity. E.g. in this version, you can have multiple kinds of aspects.
>
> Thanks,
> -lorro
>
>> On 5 Jul 2026, at 16:22, Ruud Rietvink via Std-Proposals <std-proposals_at_[hidden]> wrote:
>>
>> On 2026-07-05 15:01, Marcin Jaczewski wrote:
>>> niedz., 5 lip 2026 o 14:11 Ruud Rietvink <ruud_at_[hidden]> napisał(a):
>>>> 1) I don't suppress base class implementations, like constructors and
>>>> destructors they are all called.
>>> But I can suppress member initialization if type is trivial:
>>> ```
>>> struct Baz
>>> {
>>> int _data[10];
>>> Baz() // no zero init of `_data`
>>> {
>>> }
>>> Baz(int i) : _data{ i } // all data are set
>>> {
>>> }
>>> };
>>> ```
>> +class() has nothing to do with variabele initialization.
>>
>>>> 2) finalizers are independent of destructors, they are called in a
>>>> different line, before the destructor line.
>>>> You don't need one to have the other.
>>>> 3) Exception handling works the same as with destructors, also
>>>> independent of each other.
>>> You missed my point, adding this finizers make type not trivial and I
>>> do not think its good thing.
>>> At least you would need update every place in standard where they
>>> refer to not-trivial destructor and add "or finalizer".
>>>
>>> Similar case we have with `virtual` , what is the point of `virtual
>>> -Foo()` when you have normal `~Foo()`?
>>>
>>> Overall signature of the finalizer should be the same or at least
>>> compatible with one from the destructor.
>> Since finalizing() is separate from destruction(), they may differ in virtuality.
>>
>> -Foo() is independent of whatever ~Foo() does. And classes that use + or - are certainly not trivial.
>>
>>
>>>> 4) Propogation to member objects? I don't understand what you mean.
>>>>
>>> ```
>>> struct Foo
>>> {
>>> Bar _member;
>>> };
>>> ```
>>>
>>> We have both `-Foo()` and `-Bar()`. When and how `-Bar()` is called?
>>> Its called right before `~Foo()` or right before `~Bar()`? or called
>>> by `-Foo()`?
>>> You can think for case `std::optional<Bar>` too where `Bar` is not a
>>> direct member of optional.
>> The same order as with destruction:
>> First -Foo(), which calls -Bar() at the end, then ~Foo() that calls ~Bar() at the end
>>>>> On 2026-07-05 13:56, Marcin Jaczewski wrote:
>>>>>> I had somehow similar idea for "finalizers" but its was more "unwind" operators
>>>>>> that are called before dstructors is called.
>>>>>>
>>>>>> Main difference would be that different types of stack "unwinds" would
>>>>>> have its own functions
>>>>>> to make difference between exception unwinding and normal scope exit.
>>>>>> Or even cancellation of coroutines. Something would be useful for db
>>>>>> transact scope cancellation.
>>>>>>
>>>>>>
>>>>>> One thing I realized in my solution is that even in your case this new
>>>>>> `+foo()` and `-foo()` operators
>>>>>> need to have the same exception specification and triviality as the
>>>>>> constructor or destructor.
>>>>>> E.g. adding `-foo() noexcept(false) { throw 1; }` would change the
>>>>>> result of `noexcept(foo{})`.
>>>>>> This should be a hard error if the destructor does not have `noexcept(false)`.
>>>>>> This is needed to avoid unexpectedly changing behavior of other code
>>>>>> than need to know this things.
>>>>>>
>>>>>> Another thing to consider is how you control base functions of this
>>>>>> initializers and finishers functions?
>>>>>> How to suppress base class implementation?
>>>>>> How to propagate it to member objects? And who and when do that?
>>>>>> Is `virtual ` required on finalizers when you have a `virtual` destructor?
>>>>>>
>>>>>> niedz., 5 lip 2026 o 13:20 Ruud Rietvink via Std-Proposals
>>>>>> <std-proposals_at_[hidden]> napisał(a):
>>>>>>> C++ object initializer and finalizer
>>>>>>> ====================================
>>>>>>> Date: 2026-07-05
>>>>>>> Version: 0.1
>>>>>>> Author: Ruud Rietvink
>>>>>>>
>>>>>>>
>>>>>>> Problem
>>>>>>> -------
>>>>>>>
>>>>>>> In the constructor and destructor of an object you cannot use virtual
>>>>>>> methods properly.
>>>>>>> So calling a virtual method in a base class to get some possible derived
>>>>>>> value is not possible.
>>>>>>> During construction and destruction there is no guaranteed time that the
>>>>>>> object is fully constructed,
>>>>>>> so that virtuality covers all the layers of the object.
>>>>>>>
>>>>>>>
>>>>>>> Possible (partial) solutions
>>>>>>> ----------------------------
>>>>>>>
>>>>>>> 1) One solution is to call an initialize() method after construction,
>>>>>>> and a finalize() method directly before destruction.
>>>>>>> This is tedious and can easily be forgotten (exceptions, end of scopes).
>>>>>>>
>>>>>>> 2) The initialize() could be run automatically in a factory, calling
>>>>>>> initialize() in the factory create() method.
>>>>>>> You would have to force that the construction only takes place through
>>>>>>> this factory by a private/friend construction,
>>>>>>> or by adding a special factory tag to the constructor arguments.
>>>>>>> This doesn't solve the finalize() method though, nor copy
>>>>>>> construction/cloning.
>>>>>>>
>>>>>>> 3) With a RAII wrapper, you could call the initialize() method in the
>>>>>>> RAII constructor and the finalize()
>>>>>>> in the RAII destructor. Together with a special constructor tag you
>>>>>>> could force the RAII constructor to be used.
>>>>>>> This can be made generic. This does require more memory (pointer in RAII
>>>>>>> object).
>>>>>>> This fails for copy construction/cloning.
>>>>>>>
>>>>>>> 4) This could be done with templated inheritance.
>>>>>>> template <typename T> class LogWrapper : public T
>>>>>>> {
>>>>>>> public:
>>>>>>> template <typename... args>
>>>>>>> LogWrapper(T&&... args) : T(std::forward<Args>(args)...)
>>>>>>> {
>>>>>>> initializeLog();
>>>>>>> }
>>>>>>>
>>>>>>> ~LogWrapper()
>>>>>>> {
>>>>>>> finalizeLog();
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> Wrapping could be nested for different purposes
>>>>>>> (LogWrapper<XXXWrapper<Class>> object(....)).
>>>>>>> This fails when the class has clone() functionality (unless said API
>>>>>>> uses some standard copyable in the Wrapper).
>>>>>>>
>>>>>>>
>>>>>>> X) For all wrapper solutions the problem is that when you want to start
>>>>>>> or stop using it, or extend it, it is a lot of
>>>>>>> coding effort.
>>>>>>>
>>>>>>>
>>>>>>> Proposal
>>>>>>> --------
>>>>>>>
>>>>>>> Proposal is to introduce an initializer method that is automatically
>>>>>>> called after the construction is complete,
>>>>>>> and a finalizer method that is automatically called before the
>>>>>>> destruction of an object.
>>>>>>> Because the finalizer is called before the destructing, the vtable is
>>>>>>> still correct and virtual calling will work correctly.
>>>>>>> Proposed names:
>>>>>>> class::+class() for initializing
>>>>>>> class::-class() for finalizing
>>>>>>>
>>>>>>> Initializer is also called after copy construction.
>>>>>>>
>>>>>>> Example:
>>>>>>> class LogBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> virtual ~LogBase() = default;
>>>>>>> ...
>>>>>>> virtual const char* const logName() = 0; // or c++26-reflection
>>>>>>>
>>>>>>> +LogBase() { logStart(logName()); }
>>>>>>> virtual -LogBase() { logEnd(logName()); }
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> class EngineBase: protected LogBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> ~EngineBase() override = default;
>>>>>>> ...
>>>>>>> virtual EngineType engineType() = 0;
>>>>>>> +EngineBase() { addToEngine(engineType()); } //
>>>>>>> Optional, otherwise default
>>>>>>> -EngineBase() override { removeFromEngine } // Optional
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>> class Derived: protected EngineBase
>>>>>>> {
>>>>>>> protected:
>>>>>>> ...
>>>>>>> EngineType engineType() override { return
>>>>>>> EngineType.Something; }
>>>>>>> const char* const logName() override { return "Derived Something"; }
>>>>>>> ...
>>>>>>> };
>>>>>>>
>>>>>>>
>>>>>>> EngineBase* base = new Derived();
>>>>>>> ...
>>>>>>> delete base;
>>>>>>>
>>>>>>>
>>>>>>> // Order:
>>>>>>>
>>>>>>> // LogBase()
>>>>>>> // EngineBase()
>>>>>>> // Derived()
>>>>>>> // Object intact.
>>>>>>> // +LogBase() (same order as constructor chain)
>>>>>>> // +EngineBase()
>>>>>>> // +Derived() (if any)
>>>>>>> // Life...
>>>>>>> // -Derived() (if any, same order as destructor chain, for all
>>>>>>> implementations of -class())
>>>>>>> // -EngineBase()
>>>>>>> // -LogBase()
>>>>>>> // Object still intact.
>>>>>>> // ~Derived()
>>>>>>> // ~EngineBase()
>>>>>>> // ~LogBase()
>>>>>>>
>>>>>>>
>>>>>>> Advantages
>>>>>>> ----------
>>>>>>>
>>>>>>> a) Easy to implement for compilers.
>>>>>>> b) Easy to optimize away for compilers, if not needed.
>>>>>>> c) No clashing new keywords.
>>>>>>> d) Completely optional and backwards compatible.
>>>>>>> e) If not used, not in the way.
>>>>>>> f) Could start a new paradigm: construct in (), initialize in +(),
>>>>>>> finalize in -(), destruct in ~().
>>>>>>> Also a lot of construction is moved to header file, these days.
>>>>>>> Also substitutes often used init() method when multiple
>>>>>>> constructors are present.
>>>>>>> --
>>>>>>> Std-Proposals mailing list
>>>>>>> Std-Proposals_at_[hidden]
>>>>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2026-07-19 06:45:10
