[parameter] aux_/void.hpp: potential undefined behavior

Hello, Here's boost/aux_/void.hpp contents, without include quards and license note, where I marked a line with a comment to refer to it below. [code] namespace boost { namespace parameter { // A placemarker for "no argument passed." // MAINTAINER NOTE: Do not make this into a metafunction struct void_ {}; namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; } } // namespace aux }} // namespace boost::parameter [/code] My question is: is it allowed to use an instance of an uninitialized empty struct? The struct void_ is empty. On line (1) a static uninitialized instance of struct void_ is defined, and it is then returned. Does the standard allow this? I can't imagine any real problems with this, but I'm curious if this has defined behavior according to the standard. A natural and simple solution to my concern is of course to change the line (1) to: static void_ instance = {}; I'd be happy to create a ticket with a patch, if my concern is valid. Regards, Kris

Krzysztof Czainski wrote:
struct void_ {};
namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; }
[snip]
My question is: is it allowed to use an instance of an uninitialized empty struct?
That uses the implicit default constructor provided by the compiler which, of course, does nothing. instance is not uninitialized. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/11/3 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
struct void_ {};
namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; }
[snip]
My question is: is it allowed to use an instance of an uninitialized empty struct?
That uses the implicit default constructor provided by the compiler which, of course, does nothing. instance is not uninitialized.
Oh, makes sense, thanks. So then, don't you think it's better to use static initialization? Or maybe it doesn't matter? I mean, if the (empty autogenerated) default constructor is called, then the compiler needs to generate some flag and an if condition, so the default constructor is only called during the first invocation of void_reference(). Of course, that can be optimized away, but isn't it just better to use static initialization here? (something like prefere pass-by-const-ref to pass-by-value) Regards, Kris

Krzysztof Czainski wrote:
2011/11/3 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
struct void_ {};
namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; }
don't you think it's better to use static initialization? Or maybe it doesn't matter?
I mean, if the (empty autogenerated) default constructor is called, then the compiler needs to generate some flag and an if condition, so the default constructor is only called during the first invocation of void_reference(). Of course, that can be optimized away, but isn't it just better to use static initialization here? (something like prefere pass-by-const-ref to pass-by-value)
I presume you mean the following: namespace aux { inline void_ & void_reference() { static void_ = {}; return instance; } } My reading of 6.7/4 in N3092 suggests that would permit initialization without the need to introduce a first call test since there is no declared default constructor and using an initializer eliminates the default constructor invocation that would lead to its definition. If we're interpreting things correctly, then, yes, this is a worthwhile tip to capture, especially in light of C++11's requirement for thread-safe initialization of function local statics. _____ Rob Stewart robert.stewart@sig.com Software Engineer using std::disclaimer; Dev Tools & Components Susquehanna International Group, LLP http://www.sig.com ________________________________ IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

2011/11/4 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
2011/11/3 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
struct void_ {};
namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; }
don't you think it's better to use static initialization? Or maybe it doesn't matter?
I mean, if the (empty autogenerated) default constructor is called, then the compiler needs to generate some flag and an if condition, so the default constructor is only called during the first invocation of void_reference(). Of course, that can be optimized away, but isn't it just better to use static initialization here? (something like prefere pass-by-const-ref to pass-by-value)
I presume you mean the following:
namespace aux { inline void_ & void_reference() { static void_ = {}; return instance; } }
Yes.
My reading of 6.7/4 in N3092 suggests that would permit initialization without the need to introduce a first call test since there is no declared default constructor and using an initializer eliminates the default constructor invocation that would lead to its definition.
If we're interpreting things correctly, then, yes, this is a worthwhile tip to capture, especially in light of C++11's requirement for thread-safe initialization of function local statics.
Then I'm glad to have suggested something sensible ;-) Regards, Kris

on Thu Nov 03 2011, Krzysztof Czainski <1czajnik-AT-gmail.com> wrote:
2011/11/3 Stewart, Robert <Robert.Stewart@sig.com>
Krzysztof Czainski wrote:
struct void_ {};
namespace aux { inline void_& void_reference() { static void_ instance; // (1) return instance; }
[snip]
My question is: is it allowed to use an instance of an uninitialized empty struct?
That uses the implicit default constructor provided by the compiler which, of course, does nothing. instance is not uninitialized.
Oh, makes sense, thanks.
So then, don't you think it's better to use static initialization? Or maybe it doesn't matter?
Yes, it would be better if these things followed the pattern used in proto for terminals, with static initialization. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Dave Abrahams
-
Krzysztof Czainski
-
Stewart, Robert