
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as namespace boost { none_t const none = ((none_t)0) ; } // namespace But if two source files contain none.hpp won't this violate the one-definition rule? What's wrong with defining none_t and none as follows: namespace boost { enum none_t {none = 0}; } This allows us to have a unique value boost::none of type boost::none_t that can be included in any number of source files without violating the ODR. Joe Gottman

Joe Gottman wrote:
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as
namespace boost { none_t const none = ((none_t)0) ; } // namespace
But if two source files contain none.hpp won't this violate the one-definition rule?
none would have internal linkage according to 7.1.5.1/2. So it wouldn't violate the ODR. But a pointer to none from one translation unit would differ from a pointer to none from a different TU.
What's wrong with defining none_t and none as follows:
namespace boost { enum none_t {none = 0}; }
This allows us to have a unique value boost::none of type boost::none_t that can be included in any number of source files without violating the ODR.
It would also avoid the pointer-to-none problem mentioned above, simply because you can't create a pointer to an enumerator. However, none_t instances of enumeration type would be implicitely convertible to int, while the member pointer version of none_t isn't. Regards, m Send instant messages to your online friends http://au.messenger.yahoo.com

Martin Wille <mw8329@yahoo.com.au> writes:
Joe Gottman wrote:
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as
namespace boost { none_t const none = ((none_t)0) ; } // namespace
But if two source files contain none.hpp won't this violate the one-definition rule?
none would have internal linkage according to 7.1.5.1/2. So it wouldn't violate the ODR. But a pointer to none from one translation unit would differ from a pointer to none from a different TU.
How about the attached? The use of an inline function avoids the ODR violation, and the use of the detail::none_helper type with private constructors as the parameter ensures that noone can actually call the function, since they cannot construct a none_helper to pass. Likewise, they cannot define another function for use as none_t, since that function cannot construct the return value. Anthony -- Anthony Williams Software Developer Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk

Anthony Williams wrote:
Martin Wille <mw8329@yahoo.com.au> writes:
Joe Gottman wrote:
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as
namespace boost { none_t const none = ((none_t)0) ; } // namespace
But if two source files contain none.hpp won't this violate the one-definition rule?
none would have internal linkage according to 7.1.5.1/2. So it wouldn't violate the ODR. But a pointer to none from one translation unit would differ from a pointer to none from a different TU.
How about the attached?
The use of an inline function avoids the ODR violation, and the use of the detail::none_helper type with private constructors as the parameter ensures that noone can actually call the function, since they cannot construct a none_helper to pass. Likewise, they cannot define another function for use as none_t, since that function cannot construct the return value.
Now we're talking ;) What I like about your solution is that it doesn't declare any type of (const) variable at all so it won't have any problems with precompiled headers in any compiler AFAICT. In fact, with this solution there is no need to separate none_t from none (need that arose only from the fact that 'none' caused problems in precompiled headers in borland -at least- but none_t had to be defined anyway) Just a comment... <iostream> doesn't need to be included. Fernando Cacciola

On Tue, 25 Jul 2006 10:40:44 -0300, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
Now we're talking ;)
Indeed you couldn't respond earlier :-P
[...]
In fact, with this solution there is no need to separate none_t from none (need that arose only from the fact that 'none' caused problems in precompiled headers in borland -at least- but none_t had to be defined anyway)
I was curious to know if the problem still existed without the unnamed namespace, but we'll probably wonder for the eternity :-) Fernando, can we also decide if this is some useful toy we want to share with the lib world or an implementation detail? PS: Anthony, that formatting of the license reference text is copyrighted by me and protected by international laws :-O -- [ Gennaro Prota, C++ developer for hire ]

Gennaro Prota wrote:
On Tue, 25 Jul 2006 10:40:44 -0300, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
Now we're talking ;)
Indeed you couldn't respond earlier :-P
[...]
In fact, with this solution there is no need to separate none_t from none (need that arose only from the fact that 'none' caused problems in precompiled headers in borland -at least- but none_t had to be defined anyway)
I was curious to know if the problem still existed without the unnamed namespace, but we'll probably wonder for the eternity :-)
I know it did and I think it still does. Borland refuses to put data in a precompiled header no matter what namespace (unnamed or not) you put it.
Fernando, can we also decide if this is some useful toy we want to share with the lib world or an implementation detail?
I don't have a strong opinion or problem with regarding this as an implementation detail, but I do need to find a nice solution, like the one Anthony just proposed. Whether this deserves to be at the root level is independent from the solution. Anyway, I think none is useful outside optional<>, specifically, for variant<>, tuple<> and even any. I take you disagree. Can you explain why? Fernando

On Tue, 25 Jul 2006 12:42:05 -0300, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
Fernando, can we also decide if this is some useful toy we want to share with the lib world or an implementation detail?
I don't have a strong opinion or problem with regarding this as an implementation detail, but I do need to find a nice solution, like the one Anthony just proposed.
Fine.
[...] Anyway, I think none is useful outside optional<>, specifically, for variant<>, tuple<> and even any.
Please don't take this as obstructionism, but I just don't know. Really.
I take you disagree. Can you explain why?
Even if it happens to be shared between three or four libraries it still doesn't belong to the root dir just for that. You could probably agree to have it in detail/, but that's going to give problems in the long run in my opinion, probably mitigated if you insert a big comment along the lines of "Caution: this component is shared between x, y and z and shall keep the following behavior and interface. Only apply workarounds if they are needed for all of x, y and z, etc.". I'd suggest discussing that with the authors of the libraries you want to share it with. If you all agree that the benefits outweigh the cost I don't have strong objections (not that I don't have ;-)) Well, not sure I was clear enough, as it's a bit late and I spent all my energies today, so don't hesitate to ask again if you feel so. -- [ Gennaro Prota, C++ developer for hire ]

Gennaro Prota wrote:
On Tue, 25 Jul 2006 12:42:05 -0300, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
I take you disagree. Can you explain why?
Even if it happens to be shared between three or four libraries it still doesn't belong to the root dir just for that. You could probably agree to have it in detail/, but that's going to give problems in the long run in my opinion, probably mitigated if you insert a big comment along the lines of "Caution: this component is shared between x, y and z and shall keep the following behavior and interface. Only apply workarounds if they are needed for all of x, y and z, etc.". I'd suggest discussing that with the authors of the libraries you want to share it with. If you all agree that the benefits outweigh the cost I don't have strong objections (not that I don't have ;-))
FWIW, it can't go under the detail folder and/or namespace. That's how I initially did it but someone noticed that "none" and "none_t" are part of the public interface for optional<>, so these must be at some "user level" space. IOW, the implementation of "none_t" and "none" are a detail, but _they_ are not. They can be considered general or specific, which is different, so if they don't go into the root folder they must go into /optional (if they are considered specific), or /utility if not. But then I don't see much of a difference between the root folder and /utility for this. Best Fernando Cacciola

On Wed, 26 Jul 2006 02:28:18 -0300, "Fernando Cacciola" <fernando_cacciola@hotmail.com> wrote:
FWIW, it can't go under the detail folder and/or namespace. That's how I initially did it but someone noticed that "none" and "none_t" are part of the public interface for optional<>, so these must be at some "user level" space.
I see. Guess I should look at the optional<> docs. I participated to its initial discussion but I don't remember the existence of none, just of a default constructor. Unexcusably I thought it was an implementation detail.
IOW, the implementation of "none_t" and "none" are a detail, but _they_ are not.
Understood. This slightly changes my perspective.
They can be considered general or specific, which is different, so if they don't go into the root folder they must go into /optional (if they are considered specific), or /utility if not.
But then I don't see much of a difference between the root folder and /utility for this.
Well, perhaps it being documented independently from optional<> in the latter case. I also find that something like boost::none doesn't suggest enough, whereas optional::none mostly does. -- [ Gennaro Prota, C++ developer for hire ]

On Wed, 26 Jul 2006 02:31:56 +0200 Gennaro Prota <gennaro_prota@yahoo.com> wrote: Sorry to break in on this thread... Gennaro, I sent you an email to the above yahoo address a while back, but have not seen a reply. I imagine you, like many others, use an unusual address for the list, and do not check it very often. If you sent a reply, please resend to the private reply address on this message.

Martin Wille wrote:
Joe Gottman wrote:
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as
namespace boost { none_t const none = ((none_t)0) ; } // namespace
But if two source files contain none.hpp won't this violate the one-definition rule?
none would have internal linkage according to 7.1.5.1/2. So it wouldn't violate the ODR. But a pointer to none from one translation unit would differ from a pointer to none from a different TU.
Does this difference matter? Fernando Cacciola

On Tue, 25 Jul 2006 10:32:29 -0300, Fernando Cacciola <fernando_cacciola@hotmail.com> wrote:
none would have internal linkage according to 7.1.5.1/2. So it wouldn't violate the ODR. But a pointer to none from one translation unit would differ from a pointer to none from a different TU.
Does this difference matter?
My opinion is that if it doesn't matter for Boost.Optional then it doesn't matter. I see none and none_t as Optional's implementation details which unfortunately went into the root directory. -- [ Gennaro Prota, C++ developer for hire ]

Joe Gottman wrote:
In order to avoid having an unnamed namespace inside a header file, none.hpp has been rewritten as
namespace boost { none_t const none = ((none_t)0) ; } // namespace
But if two source files contain none.hpp won't this violate the one-definition rule? What's wrong with defining none_t and none as follows:
namespace boost { enum none_t {none = 0}; }
This allows us to have a unique value boost::none of type boost::none_t that can be included in any number of source files without violating the ODR.
Hi Joe, Sorry I couldn't respond earlier (having two jobs is killing me, although I can't say I don't enjoy it at the end of the month ;) As Martin said the problem with an enum is that it isn't type-safe, and in the particular case of optional<> that is very important because '0' is a "valid" value (so it's much more important than with a smart pointer) Fernando Cacciola
participants (6)
-
Anthony Williams
-
Fernando Cacciola
-
Gennaro Prota
-
Jody Hagins
-
Joe Gottman
-
Martin Wille