[utility/value_init] boost::value_initialized<T> direct-initialized?

Can anybody please have a look at the following feature request by Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He proposed to add an explicit constructor, value_initialized(T const&), to boost::value_initialized<T>. This constructor would copy the value of its argument to the object held by value_initialized<T>. When such a constructor would be added, an object held by value_initialized<T> might no longer be value-initialized. Instead it might be direct-initialized. Does anybody have any moral (?) objections against the idea that value_initialized<T> might hold a non-value-initialized object? Personally I think it would be useful to allow the wrapped object to be direct-initialized. But I do think there's a small risk that the new explicit constructor might cause ambiguities in legacy user code. Therefor I suggested adding an extra "tag" parameter to the new constructor, of a new type, boost::direct_initialized_t: struct direct_initialized_t { }; value_initialized(T const&, direct_initialized_t) Does anyone else also think that's a good idea? Or does anyone prefer the explicit value_initialized(T const&) constructor originally proposed by Edward? See also the thread starting at: "Re: [boost] Transfer of Maintenance Rights (utility/value_init)" http://lists.boost.org/Archives/boost/2010/03/164125.php Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Niels Dekker - address until 2010-10-10 wrote:
Can anybody please have a look at the following feature request by Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He proposed to add an explicit constructor, value_initialized(T const&), to boost::value_initialized<T>. This constructor would copy the value of its argument to the object held by value_initialized<T>.
When such a constructor would be added, an object held by value_initialized<T> might no longer be value-initialized. Instead it might be direct-initialized. Does anybody have any moral (?) objections against the idea that value_initialized<T> might hold a non-value-initialized object?
Personally I think it would be useful to allow the wrapped object to be direct-initialized. But I do think there's a small risk that the new explicit constructor might cause ambiguities in legacy user code. Therefor I suggested adding an extra "tag" parameter to the new constructor, of a new type, boost::direct_initialized_t:
struct direct_initialized_t { }; value_initialized(T const&, direct_initialized_t)
Does anyone else also think that's a good idea? Or does anyone prefer the explicit value_initialized(T const&) constructor originally proposed by Edward?
See also the thread starting at: "Re: [boost] Transfer of Maintenance Rights (utility/value_init)" http://lists.boost.org/Archives/boost/2010/03/164125.php
Kind regards,
Niels
Is defining a new template class (e.g., value_or_direct_initialized<T>, or whatever) out of the question? Just a suggestion, and not confident it's a good one... - Jeff

Can anybody please have a look at the following feature request by Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He proposed to add an explicit constructor, value_initialized(T const&), to boost::value_initialized<T>. This constructor would copy the value of its argument to the object held by value_initialized<T>.
When such a constructor would be added, an object held by value_initialized<T> might no longer be value-initialized. Instead it might be direct-initialized. Does anybody have any moral (?) objections against the idea that value_initialized<T> might hold a non-value-initialized object?
Jeffrey Hellrung wrote:
Is defining a new template class (e.g., value_or_direct_initialized<T>, or whatever) out of the question? Just a suggestion, and not confident it's a good one...
Thanks for the suggestion, Jeffrey! I like it, actually. :-) Maybe we could simply call the new template class boost::initialized<T>. I can think of two ways to implement boost::initialized<T> (and adapt value_initialized<T> accordingly): The implementation of boost::initialized could be simply copied from the old value_initialized<T>, but having an extra constructor, initialized(T const&). The new value_initialized<T> could then be implemented in terms of boost::initialized<T>: template<class T> class value_initialized { initialized<T> m_data; public: // Forwarding to m_data member functions: T const & data() const; T& data(); void swap(value_initialized &); operator T const &() const; operator T&(); }; Or boost::initialized<T> could be derived from boost::value_initialized<T>: template<class T> class initialized: public value_initialized<T> { public: initialized(T const& arg): value_initialized(arg) {} void swap(initialized &); }; In that case, value_initialized<T> would still need the extra constructor, value_initialized(T const&), but it could be declared protected. What do you think? Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Niels Dekker - address until 2010-10-10 wrote:
Can anybody please have a look at the following feature request by Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He proposed to add an explicit constructor, value_initialized(T const&), to boost::value_initialized<T>. This constructor would copy the value of its argument to the object held by value_initialized<T>.
When such a constructor would be added, an object held by value_initialized<T> might no longer be value-initialized. Instead it might be direct-initialized. Does anybody have any moral (?) objections against the idea that value_initialized<T> might hold a non-value-initialized object?
Jeffrey Hellrung wrote:
Is defining a new template class (e.g., value_or_direct_initialized<T>, or whatever) out of the question? Just a suggestion, and not confident it's a good one...
Thanks for the suggestion, Jeffrey! I like it, actually. :-) Maybe we could simply call the new template class boost::initialized<T>.
initialized<T> was actually my initial thought; I chose a crappy name on purpose ;)
I can think of two ways to implement boost::initialized<T> (and adapt value_initialized<T> accordingly): [...]
I'm partial to value_initialized being implemented in terms of initialized, but it is strictly an implementation detail, right? Also, your initialized<T> does not have a default constructor. This makes sense, but I'm just double-checking that this is a conscious decision and not an oversight. - Jeff

Jeffrey Hellrung wrote:
Also, your initialized<T> does not have a default constructor. This makes sense, but I'm just double-checking that this is a conscious decision and not an oversight.
Actually, on second thought, this doesn't make sense, but I might be missing something...why would one use an initialized<T> with no default constructor, rather than just T itself? - Jeff

Jeffrey Hellrung wrote:
initialized<T> was actually my initial thought; I chose a crappy name on purpose ;)
Cool :-)
I can think of two ways to implement boost::initialized<T> (and adapt value_initialized<T> accordingly): [...]
I'm partial to value_initialized being implemented in terms of initialized
Me too :-) I think there's a leak in the design when boost::initialized inherits publicly from boost::value_initialized. You know, currently any object held by value_initialized is either value-initialized or copy-constructed from another object held by value_initialized. So in the end, any such object originates from a value-initialized object. I would like to keep it that way!
Also, your initialized<T> does not have a default constructor. This makes sense, but I'm just double-checking that this is a conscious decision and not an oversight.
No, it's an oversight, sorry! I did not test any code from my last mail! BTW I'm not entirely sure if the initialized(T const&) constructor would need an "explicit" keyword. What do you think? Should the following be forbidden? boost::initialized<int> i = 42; If so, we might as well make it even more explicit, by adding a "tag" parameter of type direct_initialized_t to the constructor, as I proposed before at https://svn.boost.org/trac/boost/ticket/3472 so that users would have to explicitly specify that they want direct-initialization: boost::initialized<int> i(42, boost::direct_initialized); What do you think? Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

AMDG Niels Dekker - address until 2010-10-10 wrote:
Also, your initialized<T> does not have a default constructor. This makes sense, but I'm just double-checking that this is a conscious decision and not an oversight.
No, it's an oversight, sorry! I did not test any code from my last mail!
BTW I'm not entirely sure if the initialized(T const&) constructor would need an "explicit" keyword. What do you think? Should the following be forbidden?
boost::initialized<int> i = 42;
If so, we might as well make it even more explicit, by adding a "tag" parameter of type direct_initialized_t to the constructor, as I proposed before at https://svn.boost.org/trac/boost/ticket/3472 so that users would have to explicitly specify that they want direct-initialization:
boost::initialized<int> i(42, boost::direct_initialized);
I'd much prefer boost::initialized to simply forward constructor arguments. The templated constructor should be explicit, because otherwise things like boost::initialized<std::vector<int> > v = 10; would compile. IMHO, it's okay if implicit conversions that would normally work for the contained type don't work, since this errs on the side of safety, but it isn't okay to make all conversions implicit. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Niels Dekker - address until 2010-10-10 wrote:
Also, your initialized<T> does not have a default constructor. This makes sense, but I'm just double-checking that this is a conscious decision and not an oversight.
No, it's an oversight, sorry! I did not test any code from my last mail!
BTW I'm not entirely sure if the initialized(T const&) constructor would need an "explicit" keyword. What do you think? Should the following be forbidden?
boost::initialized<int> i = 42;
If so, we might as well make it even more explicit, by adding a "tag" parameter of type direct_initialized_t to the constructor, as I proposed before at https://svn.boost.org/trac/boost/ticket/3472 so that users would have to explicitly specify that they want direct-initialization:
boost::initialized<int> i(42, boost::direct_initialized);
I'd much prefer boost::initialized to simply forward constructor arguments. The templated constructor should be explicit, because otherwise things like
boost::initialized<std::vector<int> > v = 10;
would compile. IMHO, it's okay if implicit conversions that would normally work for the contained type don't work, since this errs on the side of safety, but it isn't okay to make all conversions implicit.
Agreed. And I don't think the boost::direct_initialized tag is necessary, MSVC compiler bugs be damned. (I primarily use MSVC9 currently.) - Jeff

Jeffrey Hellrung wrote:
The templated constructor should be explicit, because otherwise things like
boost::initialized<std::vector<int> > v = 10;
would compile. IMHO, it's okay if implicit conversions that would normally work for the contained type don't work, since this errs on the side of safety, but it isn't okay to make all conversions implicit.
Agreed.
Leaving out the "explicit" keyword from the initialized(const T&) constructor of initialized<T> won't make Steven's example compile (as I wrote before). In what particular situation would you need to use boost::initialized<T>, including the new initialized(const T&) constructor, instead of just the old value_initialized<T>? I think /the/ motivating use case for boost::initialized<T> is about member data initialization: template <typename T> class foo { std::string m_name; boost::initialized<T> m_data; public: foo(); foo(const foo&); foo(const T&, std::string); }; In this case, some of foo's constructors may want m_data to be value-initialized, but others need to do direct-initialization. Do you agree that its support for member data initialization would be the main reason for having boost::initialized<T>?
And I don't think the boost::direct_initialized tag is necessary, MSVC compiler bugs be damned.
Sorry, I'm not sure what you mean. It's certainly important to me to have something that works on MSVC. Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Niels Dekker - address until 2010-10-10 wrote:
I think /the/ motivating use case for boost::initialized<T> is about member data initialization: [...] Do you agree that its support for member data initialization would be the main reason for having boost::initialized<T>?
Yes.
And I don't think the boost::direct_initialized tag is necessary, MSVC compiler bugs be damned.
Sorry, I'm not sure what you mean. It's certainly important to me to have something that works on MSVC.
Is that MSVC bug (the one referenced in the value_initialized ticket...no link handy at the moment) not "workaroundable" by explicitly defining the derived class' copy constructor? And isn't it only a problem when the base class has a constructor other than the copy constructor that that a const derived& can bind to? Perhaps I need to go back and reread the Microsoft ticket... - Jeff

Do you agree that its support for member data initialization would be the main reason for having boost::initialized<T>?
Jeffrey Hellrung wrote:
Yes.
Within the context of member data initialization, the "explicit" keyword doesn't do anything. (For example, when the class has a data member of type boost::initialized<T>.) That's why I though the extra boost::direct_initialized_t tag parameter might be useful. Clearly so far I haven't convinced anyone. But I realize such a tag parameter will be less relevant when we're going to introduce a new initialized<T> template class, instead of modifying the interface of the old boost::value_initialized<T>. Fernando's boost::value_initialized<T> has been around for so long that I think backward-compatibility should be taken into account.
Is that MSVC bug (the one referenced in the value_initialized ticket...no link handy at the moment) not "workaroundable" by explicitly defining the derived class' copy constructor?
MSVC bug (reported independently by both srconchiwa and Edward Diener): http://connect.microsoft.com/VisualStudio/feedback/details/423737/default-co... http://connect.microsoft.com/VisualStudio/feedback/details/522094/warning-c4... value_initialized ticket by Edward: https://svn.boost.org/trac/boost/ticket/3472 (Yes, I added a reference to our discussion!)
And isn't it only a problem when the base class has a constructor other than the copy constructor that that a const derived& can bind to? Perhaps I need to go back and reread the Microsoft ticket...
Honestly the MSVC bug just made me more aware that copy-constructors and non-copy-constructors can get confused, in a generic context. But the example I added to the ticket (#3472) would also be ambiguous on other compilers, when value_initialized(T const&) would be added: class my_integer { value_initialized<int> m_data; public: operator value_initialized<int>() const; operator int() const; }; int main() { my_integer my; value_initialized<int> val(my); } See http://codepad.org/zukxSDbB Remaining question, triggered by the comments by Steven: should the new direct-initializing boost::initialized<T> constructor itself be a template? In that case, the "explicit" keyword certainly would make more sense to me: // Note: untested! template<class T> class initialized { ... public: initialized(); template<class U> explicit initialized(U const&); T const & data() const; T& data(); void swap(initialized &); operator T const &() const; operator T&(); }; What do you think? Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Niels Dekker - address until 2010-10-10 wrote:
Do you agree that its support for member data initialization would be the main reason for having boost::initialized<T>?
Jeffrey Hellrung wrote:
Yes.
Within the context of member data initialization, the "explicit" keyword doesn't do anything. (For example, when the class has a data member of type boost::initialized<T>.) That's why I though the extra boost::direct_initialized_t tag parameter might be useful. Clearly so far I haven't convinced anyone. But I realize such a tag parameter will be less relevant when we're going to introduce a new initialized<T> template class, instead of modifying the interface of the old boost::value_initialized<T>. Fernando's boost::value_initialized<T> has been around for so long that I think backward-compatibility should be taken into account.
To me, the tag is a syntactic wart, but I understand your concerns, and you've clearly considered this problem more than I have... [...]
Honestly the MSVC bug just made me more aware that copy-constructors and non-copy-constructors can get confused, in a generic context. But the example I added to the ticket (#3472) would also be ambiguous on other compilers, when value_initialized(T const&) would be added:
class my_integer { value_initialized<int> m_data; public: operator value_initialized<int>() const; operator int() const; };
int main() { my_integer my; value_initialized<int> val(my); }
Point taken. See below.
Remaining question, triggered by the comments by Steven: should the new direct-initializing boost::initialized<T> constructor itself be a template? In that case, the "explicit" keyword certainly would make more sense to me:
// Note: untested! template<class T> class initialized { ... public: initialized();
template<class U> explicit initialized(U const&);
T const & data() const; T& data(); void swap(initialized &); operator T const &() const; operator T&(); };
What do you think?
What do you think about using the templated constructor *and* SFINAE out via enable_if the binding of U to initialized<T> (or, maybe, to any class derived from initialized<T>)? What problems does that have? - Jeff

Jeffrey Lee Hellrung, Jr. wrote:
What do you think about using the templated constructor *and* SFINAE out via enable_if the binding of U to initialized<T> (or, maybe, to any class derived from initialized<T>)?
SFINAE/enable_if might be interesting indeed, but I'm not sure if it's really necessary. And I don't think it will help to work around the specific MSVC bug <http://connect.microsoft.com/VisualStudio/feedback/details/423737>. Here is an example that fails to compile on MSVC because of the compiler bug. Please let me know if you can fix it by SFINAE. (But I'm afraid it won't work.) ////////////////////////////////////////////////// namespace boost { template<class T> class initialized { T m_data; public: initialized() : m_data() { } initialized(const initialized& arg) : m_data(arg.m_data) { } template<class U> explicit initialized(const U& arg) : m_data(arg) { } operator T&() { return m_data; } operator const T&() const { return m_data; } }; } ////////////////////////////////////////////////// // USER CODE STARTS HERE class my_initialized_int: boost::initialized<int> { }; int main() { my_initialized_int i1; my_initialized_int i2 = i1; } ////////////////////////////////////////////////// The example above compiles well on Comeau 4.3.10.1 <www.comeaucomputing.com/tryitout> and GCC 4.1.2 <http://codepad.org/NCZKJ3OE>. But it fails on MSVC, as www.dinkumware.com/exam says: error C2247: 'boost::initialized<T>::operator const int &' not accessible because 'my_initialized_int' uses 'private' to inherit from 'boost::initialized<T>' Would boost::initialized<T> really need to have a /templated/ constructor, initialized(const U&)? Wouldn't a non-templated initialized(const T&) be sufficient, for initialized<T>? Note that that's just what Edward was asking for <https://svn.boost.org/trac/boost/ticket/3472>. Do you have a motivating use case for a templated constructor of initialized<T>? Anyway, I /do/ think that it would be useful to add move semantics, by adding a initialized(T&&) constructor, for those compilers that support rvalue references. Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

AMDG Niels Dekker - address until 2010-10-10 wrote:
Jeffrey Lee Hellrung, Jr. wrote:
What do you think about using the templated constructor *and* SFINAE out via enable_if the binding of U to initialized<T> (or, maybe, to any class derived from initialized<T>)?
SFINAE/enable_if might be interesting indeed, but I'm not sure if it's really necessary. And I don't think it will help to work around the specific MSVC bug <http://connect.microsoft.com/VisualStudio/feedback/details/423737>.
Here is an example that fails to compile on MSVC because of the compiler bug. Please let me know if you can fix it by SFINAE. (But I'm afraid it won't work.)
I'm not sure if I missed something, but this seems to work template<class U> explicit initialized(const U& arg, typename boost::disable_if<boost::is_base_and_derived<initialized, U> >::type* = 0) In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Niels Dekker - address until 2010-10-10 wrote:
Jeffrey Lee Hellrung, Jr. wrote:
What do you think about using the templated constructor *and* SFINAE out via enable_if the binding of U to initialized<T> (or, maybe, to any class derived from initialized<T>)?
SFINAE/enable_if might be interesting indeed, but I'm not sure if it's really necessary. And I don't think it will help to work around the specific MSVC bug <http://connect.microsoft.com/VisualStudio/feedback/details/423737>.
Here is an example that fails to compile on MSVC because of the compiler bug. Please let me know if you can fix it by SFINAE. (But I'm afraid it won't work.)
I'm not sure if I missed something, but this seems to work
template<class U> explicit initialized(const U& arg, typename boost::disable_if<boost::is_base_and_derived<initialized, U> >::type* = 0)
That's what I had in mind. Although, echoing Steven: Maybe we should just settle for the dead plain simple initialized(const T&) constructor. - Jeff

Jeffrey Lee Hellrung, Jr. wrote:
Although, echoing Steven: Maybe we should just settle for the dead plain simple initialized(const T&) constructor.
I'm not sure if Steven said so, but I certainly did :-D Please have a look at the patch I just attached to ticket #3472, having the simple initialized(const T&) constructor: https://svn.boost.org/trac/boost/attachment/ticket/3472/initialized.patch Do you think it's okay? Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Niels Dekker - address until 2010-10-10 wrote:
Jeffrey Lee Hellrung, Jr. wrote:
Although, echoing Steven: Maybe we should just settle for the dead plain simple initialized(const T&) constructor.
I'm not sure if Steven said so, but I certainly did :-D
Okay, maybe I got the email exchanges confused, my apologies ;)
Please have a look at the patch I just attached to ticket #3472, having the simple initialized(const T&) constructor: https://svn.boost.org/trac/boost/attachment/ticket/3472/initialized.patch
Do you think it's okay?
Looks basically like how I had imagined. - Jeff

https://svn.boost.org/trac/boost/attachment/ticket/3472/initialized.patch Do you think it's okay?
Jeffrey Lee Hellrung, Jr. wrote:
Looks basically like how I had imagined.
Thanks! I'll commit our new boost::initialized<T> to the trunk when Fernando Cacciola has also taken a look. It won't be included with Boost release version 1.43.0, I'm afraid, especially because unit tests and documentation still need to be written. But I think Boost version 1.44 is a feasible target. Note that there's also some progress on the other open value_init issue, <https://svn.boost.org/trac/boost/ticket/3869>, submitted by Aleksey Gurtovoy. The idea is to have a defect macro, BOOST_NO_COMPLETE_VALUE_INITIALIZATION, which is defined when a compiler itself has not have completely implemented value-initialization. John Maddock and I have been looking at how to test such a macro, during the Easter days. The std::memset call inside value_init.hpp could then be made conditional, based upon this macro. Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

SFINAE/enable_if might be interesting indeed, but I'm not sure if it's really necessary. And I don't think it will help to work around the specific MSVC bug <http://connect.microsoft.com/VisualStudio/feedback/details/423737>.
Steven Watanabe wrote:
I'm not sure if I missed something, but this seems to work
template<class U> explicit initialized(const U& arg, typename boost::disable_if<boost::is_base_and_derived<initialized, U>
::type* = 0)
Yes it does! Thanks, Steven. Sorry, I was wrong, thinking that it wouldn't work! Still I'd rather postpone adding a templated initialized(const U&) constructor until we have a user request and/or a motivating use case. For the time being I think a non-templated initialized(const T&) constructor should be sufficient, for the new boost::initialized<T>. Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

AMDG Niels Dekker - address until 2010-10-10 wrote:
Honestly the MSVC bug just made me more aware that copy-constructors and non-copy-constructors can get confused, in a generic context. But the example I added to the ticket (#3472) would also be ambiguous on other compilers, when value_initialized(T const&) would be added:
class my_integer { value_initialized<int> m_data; public: operator value_initialized<int>() const; operator int() const; };
int main() { my_integer my; value_initialized<int> val(my); }
Um. Why do you /want/ to do this? In Christ, Steven Watanabe

the example I added to the ticket (#3472) would also be ambiguous on other compilers, when value_initialized(T const&) would be added:
class my_integer { value_initialized<int> m_data; public: operator value_initialized<int>() const; operator int() const; };
int main() { my_integer my; value_initialized<int> val(my); }
Steven Watanabe wrote:
Um. Why do you /want/ to do this?
I don't know, it's just an example. my_integer::operator value_initialized<int>() might do some extra checks that my_integer::operator int() does not. Or whatever. You know, boost::value_initialized<T> has been around for very long already, so I think it's possible that adding a value_initialized(T const&) constructor might break some legacy user code. But please let me know if you have a better example! Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

AMDG Niels Dekker - address until 2010-10-10 wrote:
Steven Watanabe wrote:
Um. Why do you /want/ to do this?
I don't know, it's just an example. my_integer::operator value_initialized<int>() might do some extra checks that my_integer::operator int() does not. Or whatever. You know, boost::value_initialized<T> has been around for very long already, so I think it's possible that adding a value_initialized(T const&) constructor might break some legacy user code. But please let me know if you have a better example!
If we're changing value_initialized, okay. But I thought we were talking about adding a new class now? Since this won't break backward compatibility, I think the most reasonable response is "don't do that." In Christ, Steven Watanabe

I'm not entirely sure if the initialized(T const&) constructor would need an "explicit" keyword. What do you think? Should the following be forbidden?
boost::initialized<int> i = 42;
If so, we might as well make it even more explicit, by adding a "tag" parameter of type direct_initialized_t to the constructor, as I proposed before at https://svn.boost.org/trac/boost/ticket/3472 so that users would have to explicitly specify that they want direct-initialization:
boost::initialized<int> i(42, boost::direct_initialized);
Steven Watanabe wrote:
I'd much prefer boost::initialized to simply forward constructor arguments.
Thanks, Steven. But would it be okay to you if boost::initialized<T> would just have a initialized(const T&) constructor? Or do you think it should be a "variadic" one, for example initialized(const U&...). I'm afraid it's hard to implement such a variadic constructor, perfectly forwarding its arguments to the internal T object, given current limitations of a lot of compilers. And personally I think it would be sufficient to just offer a initialized(const T&) constructor. But please tell me if you think otherwise.
The templated constructor should be explicit, because otherwise things like
boost::initialized<std::vector<int> > v = 10;
would compile.
Please note that I never suggested to make your example compile. I was only wondering whether or not the following should compile: boost::initialized<std::vector<int> > v = std::vector<int>(10); So in fact, after initialization by means of initialized(const T&), lhs and rhs will have the same value. In that case, isn't copy-initialization appropriate? Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Hi People, OK, only seven months after Eduard's inital request I finally made the time to really look at it :) Jeffrey Hellrung wrote:
Niels Dekker - address until 2010-10-10 wrote:
Can anybody please have a look at the following feature request by Edward Diener? https://svn.boost.org/trac/boost/ticket/3472 He proposed to add an explicit constructor, value_initialized(T const&), to boost::value_initialized<T>. This constructor would copy the value of its argument to the object held by value_initialized<T>.
OK, so as Niels quite clearly figured out, what Eduard wanted was this wrapper to contain values either value or directrly initialized.
When such a constructor would be added, an object held by value_initialized<T> might no longer be value-initialized. Instead it might be direct-initialized.
Does anybody have any moral (?) objections against the idea that value_initialized<T> might hold a non-value-initialized object?
A reasonable objection would be that a new comer would rightly question: why is it called "value_" then, when in effect I'm direct-initializing it instead in
Indeed. this case here? Of course, a quick answer would be that the class guarantess value initialization only when there is none, logicaly, and that the name is really short for value_or_direct_initialized.
Personally I think it would be useful to allow the wrapped object to be direct-initialized. But I do think there's a small risk that the new explicit constructor might cause ambiguities in legacy user code.
Therefor I suggested adding an extra "tag" parameter to the new constructor, of a new type, boost::direct_initialized_t:
struct direct_initialized_t { }; value_initialized(T const&, direct_initialized_t)
Does anyone else also think that's a good idea? Or does anyone prefer the explicit value_initialized(T const&) constructor originally proposed by Edward?
I'm not religiously against the additional parameter, but I definitely wouldn't
I followed ALL of the MSVC bug reports, threads, even related CCW issues, and I fail to see how in OUR case here there could be any ambiguity? The MSVC (and GCC) bugs all boils down to a resolution mistake rooted on certain "constructors that copy" in the base class. These bugs are not about a mistaken ambiguity, which would turn a legal program into ill-formed, forcing the programmer to change it, but about a wrong selection, whose consequences are quite different.. so let's see: None of these bugs reported show up when the choices are (a) the copy constructor and (b) a **non-template** explicit constructor, as in our case. So, I don't see why would we have to expect that to happen here. But even if a compiler would get it wrong, as in those bugs, and called the wrong ctor, the net effect would nevertheless be the same in our very specific case (the worst that could happen is an extra temporary surely ellided anyway). On the other front, regarding Neil's other sources of ambiguity... well, honestly, if a user writes such code, I'm more than happy to put him out his missery by not letting him compile such a mounstrocity anymore :) Or can you come up with a less aritificial and contorted used case that could result in ambiguity? like it for no reason, and after all the analysis about what could effectively happen, I don't see any reason for complicating it. So I'd go for Eduard's patch.
See also the thread starting at: "Re: [boost] Transfer of Maintenance Rights (utility/value_init)" http://lists.boost.org/Archives/boost/2010/03/164125.php
Kind regards,
Niels
Is defining a new template class (e.g., value_or_direct_initialized<T>, or whatever) out of the question? Just a suggestion, and not confident it's a good one...
OTOH, there is a new angle here... Having said that I'm more than happy with an extended value_initialized<> that accepts direct initialization via a straightforward ctor, it *could* be argued that having both initialized and value_initialized makes sense all by itself. But let's see: I can imagine myself explaining that "initialize<T> m(v)" does direct-initialization, then that, OTOH, "initialized<T> m;" does value-initialization, since there is no explicit initialization in this case. Newcomers would say "OK, I follow". Then I would proceed and explain that, "value_initialized<T> m" is also doing value-initialization... What? why would I ever want to use that one then, having the other?? And then I would answer: hmmm, right, you don't. So the slipts ends up being just to prevent user code to break when we add the feature... Since I don't really see user code being broken here, this split makes no sense to me. What would have made sense is to have called this "initialized" to begin with, and feature it with direct-initialization super powers! But adding this *now* and leave its old ancestor for the elder? don't like it. So, let's just add the plain and simple explicit ctor :) [Neils, feel free to argue back :) Best -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

Fernando Cacciola wrote:
OK, only seven months after Eduard's inital request I finally made the time to really look at it :)
Thanks, Fernando! Sorry for snipping out large pieces of your reply.
So I'd go for Eduard's patch.
For anyone else following this discussion, Eduard's patch, which adds direct-initialization to boost::value_initialized<T>, is at https://svn.boost.org/trac/boost/attachment/ticket/3472/value_init.patch
So, let's just add the plain and simple explicit ctor :) [Neils, feel free to argue back :)
Okay, here I go: Suppose, a long time ago you wrote a class named foo::const_iterator, which provides const access to foo's items. Now you happen to need non-const access as well. Will you add this as an extra feature to foo::const_iterator? I hope not. I hope, you'd rather write an extra class, named foo::iterator. Now we're having a template class named boost::value_initialized<T>, which provides value-initialization. And we happen to need non-value-initialization as well, as reported by #3472. I still believe an extra boost::initialized<T> template class is the best choice. As was suggested by Jeff: https://svn.boost.org/trac/boost/attachment/ticket/3472/initialized.patch Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Fernando Cacciola wrote:
I can imagine myself explaining that "initialize<T> m(v)" does direct-initialization, then that, OTOH, "initialized<T> m;" does value-initialization, since there is no explicit initialization in this case.
Why does initialized<T> need to have a default constructor? _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; 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.

Stewart, Robert wrote:
Fernando Cacciola wrote:
I can imagine myself explaining that "initialize<T> m(v)" does direct-initialization, then that, OTOH, "initialized<T> m;" does value-initialization, since there is no explicit initialization in this case.
Why does initialized<T> need to have a default constructor?
Because if it wasn't default-constructible, why would you use it (when a T object would suffice)? The motivating example (I believe) is when you have a class member of type initialized<T>, and you want the default constructor of the class to value initialize the data member. (You also want a (const T&) constructor that direct intializes the data member; otherwise, value_initialized<T> would suffice.) - Jeff

Jeffrey Lee Hellrung, Jr. wrote:
Stewart, Robert wrote:
Fernando Cacciola wrote:
I can imagine myself explaining that "initialize<T> m(v)" does direct-initialization, then that, OTOH, "initialized<T> m;" does value-initialization, since there is no explicit initialization in this case.
Why does initialized<T> need to have a default constructor?
Because if it wasn't default-constructible, why would you use it (when a T object would suffice)?
The motivating example (I believe) is when you have a class member of type initialized<T>, and you want the default constructor of the class to value initialize the data member. (You also want a (const T&) constructor that direct intializes the data member; otherwise, value_initialized<T> would suffice.)
Given that, I have to agree with Fernando that initialize is merely a superset of value_initialize and can be harder to explain unless it derives from value_initialize (even if it shares nothing from the base and only makes clear that it is a superset). _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; 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.

Robert Stewart wrote:
Given that, I have to agree with Fernando that initialize is merely a superset of value_initialize and can be harder to explain unless it derives from value_initialize (even if it shares nothing from the base and only makes clear that it is a superset).
Thanks, Robert. But do you mean public inheritance? You know, I once considered having initialized<T> publicly derived from value_initialized<T>: http://lists.boost.org/Archives/boost/2010/03/164356.php But then I realized that it would imply that any "initialized" object is also a value_initialized object. While certainly an initialized object does not need to be value-initialized. Therefor I think composition is preferable to public inheritance, in this case. I really don't see what's wrong about the patch I submitted, having value_initialized<T> containing a private initialized<T> data member: https://svn.boost.org/trac/boost/attachment/ticket/3472/initialized.patch Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Hi Niels,
Robert Stewart wrote:
Given that, I have to agree with Fernando that initialize is merely a superset of value_initialize and can be harder to explain unless it derives from value_initialize (even if it shares nothing from the base and only makes clear that it is a superset).
Thanks, Robert. But do you mean public inheritance? You know, I once considered having initialized<T> publicly derived from value_initialized<T>: http://lists.boost.org/Archives/boost/2010/03/164356.php
Let's see: Given a set 's' and a superset 'S', we derive S from s because by LSP we need to be able to substitute s by S. That is, pass an S where an s is asked for. So, IF initialized<> is indeed a superset of value_initialized<> then the derivation that Robert proposed and you attempted at first is definitely correct.
But then I realized that it would imply that any "initialized" object is also a value_initialized object. While certainly an initialized object does not need to be value-initialized.
So then you realized that in a certain interpretation of the meaning of value_initialized<>, it is NOT really a subset of initialized<>. Why? I think the differnce is in the actual semantics of the name... do we mean value_initializED or value_intializaBLE? Clearly, your view here is that an object value_initialized<> is *specifically* having the invariant that its value is neccesarily value initialized, which is entirely differnt from saying that its value if neccesarily never left uninitialized, so it is *at least* value initialized. Those are two clearly different classes. If your current interpretation is the one to go for, then the issue is very simply settled because then, Eduard's request has no place to begin with, and by neccesity we need an entirely new class.
Therefor I think composition is preferable to public inheritance
I wouldn't put it in those terms. Depending on what we define these classes to be, one or the other is the only correct choice. Having said all that.. IF we would agree to consider that value_initialized<> guarantess that it can only contain a value-initialized object, then your proposal would be definitely correct. OTOH, what's the use of such a class?? I can't see any. Certainly I always considered that the invariant is that it cannot be left unitialized rather that it cannot be direcly-initialized. Your other line of argument about const and non-const iterator classes is independent and I'll address it on aother post. Best -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

You know, I once considered having initialized<T> publicly derived from value_initialized<T>: http://lists.boost.org/Archives/boost/2010/03/164356.php
Fernando Cacciola wrote:
Let's see: Given a set 's' and a superset 'S', we derive S from s because by LSP we need to be able to substitute s by S. That is, pass an S where an s is asked for. So, IF initialized<> is indeed a superset of value_initialized<> then the derivation that Robert proposed and you attempted at first is definitely correct.
Thank, Fernando. I know the LSP is a very important OO principle. But are you saying that Bacon Cheeseburger Pizza is a vegetarian meal, just because it's a superset thereof? BTW, personally I prefer to only use public inheritance when the base class has a virtual destructor (as a rule of thumb). But I think the price of adding a virtual table to value_initialized<> is simply too high.
But then I realized that it would imply that any "initialized" object is also a value_initialized object. While certainly an initialized object does not need to be value-initialized.
So then you realized that in a certain interpretation of the meaning of value_initialized<>, it is NOT really a subset of initialized<>.
Why? I think the differnce is in the actual semantics of the name... do we mean value_initializED or value_intializaBLE?
Good question. Currently, boost::value_initialized<T> requires that T is "value-initializable" (i.e., DefaultConstructible), in order to construct value_initialized<T>. When you're adding the proposed value_initialized(const T&) constructor (ticket #3472), value_initialized<T> will no longer require that T is value-initializable, in order to construct value_initialized<T>. Sounds counter-intuitive to me. [snip]
IF we would agree to consider that value_initialized<> guarantess that it can only contain a value-initialized object, then your proposal would be definitely correct.
OTOH, what's the use of such a class?? I can't see any.
C'mon, your boost::value_initialized<T> has been around for more than 7 years, and now you think it has always been useless??
Certainly I always considered that the invariant is that it cannot be left unitialized rather that it cannot be direcly-initialized.
I thought the purpose of value_initialized<> was to provide a generic way to do value-initialization; and to guarantee that the constructed object is indeed value-initialized. Please correct me if I'm wrong. Anyway, I also think it makes code analysis (reviewing Boost user code) easier when the reviewer can safely assume that a value_initialized<T> object always originates from value-initialization. Just like it has always been up to now.
Your other line of argument about const and non-const iterator classes is independent and I'll address it on aother post.
Please do. :-) Kind regards, Niels -- Niels Dekker http://www.xs4all.nl/~nd/dekkerware Scientific programmer at LKEB, Leiden University Medical Center

Hi Niels,
You know, I once considered having initialized<T> publicly derived from value_initialized<T>: http://lists.boost.org/Archives/boost/2010/03/164356.php
Fernando Cacciola wrote:
Let's see: Given a set 's' and a superset 'S', we derive S from s because by LSP we need to be able to substitute s by S. That is, pass an S where an s is asked for. So, IF initialized<> is indeed a superset of value_initialized<> then the derivation that Robert proposed and you attempted at first is definitely correct.
Thank, Fernando. I know the LSP is a very important OO principle. But are you saying that Bacon Cheeseburger Pizza is a vegetarian meal, just because it's a superset thereof?
LOL, certainly not. What I meant to say is that in our case, the choice between your patch vs inheritance is expressing, in reality, two completely different things (instead of being just a design decision). I just attempted to argue why and how.
BTW, personally I prefer to only use public inheritance when the base class has a virtual destructor (as a rule of thumb).
I do too.
But I think the price of adding a virtual table to value_initialized<> is simply too high.
Absolutely. Anyway, as I said, by choosing one or the other, in this case, we are defining two totally different abstractions, so IMO, the decision should have nothing to do with the technical convenience but with what we want these things to be.
But then I realized that it would imply that any "initialized" object is also a value_initialized object. While certainly an initialized object does not need to be value-initialized.
So then you realized that in a certain interpretation of the meaning of value_initialized<>, it is NOT really a subset of initialized<>.
Why? I think the differnce is in the actual semantics of the name... do we mean value_initializED or value_intializaBLE?
Good question. Currently, boost::value_initialized<T> requires that T is "value-initializable" (i.e., DefaultConstructible), in order to construct value_initialized<T>. When you're adding the proposed value_initialized(const T&) constructor (ticket #3472), value_initialized<T> will no longer require that T is value-initializable, in order to construct value_initialized<T>. Sounds counter-intuitive to me.
[snip]
IF we would agree to consider that value_initialized<> guarantess that it can only contain a value-initialized object, then your proposal would be definitely correct.
OTOH, what's the use of such a class?? I can't see any.
C'mon, your boost::value_initialized<T> has been around for more than 7 years, and now you think it has always been useless??
See my next response.. that'll clarify my statement.
Certainly I always considered that the invariant is that it cannot be left unitialized rather that it cannot be direcly-initialized.
I thought the purpose of value_initialized<> was to provide a generic way to do value-initialization; and to
guarantee that the constructed object is indeed value-initialized. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Please correct me if I'm wrong.
I can't say that you are wrong, because clearly that is a perfectly valid interpretation. OTOH, I really never intended the purpose to be that :) That's why I said that I couldn't see uses for a class that is strictly *value* initialized instead of value initialized *by default at the very least* (which was my intention.. just that it never ended up uninitialized) If I had, then as I said before, I would have instantly reacted to Eduard's request arguing that what he wanted was perfectly fine but did not belong to my class
Anyway, I also think it makes code analysis (reviewing Boost user code) easier when the reviewer
can safely assume that a value_initialized<T> object always originates from value-initialization. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (1)
Just like it has always been up to now. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (2)
OK, what you just said totally settles it IMO :) At the very least *you* are assuming, or always assumed, (1), and the actual code I wrote was indeed 'forcing' that assumtion. (because of (2)) So it doesn't matter what my intention was, nor that I think I should have added the direct-initializer Eduard requested. That class has always been comunicating something else: (1), so I don't really have a responsible choice now but to add initialized<> as a new thing. I don't think I would ever use value_initialized<> INSTEAD of initialized<>, but that's just me. Having said that... your specific implementation of these two classes are exactly what I would have done, so, please go ahead and commit your patch. Best -- Fernando Cacciola SciSoft Consulting, Founder http://www.scisoft-consulting.com

Niels Dekker wrote:
Robert Stewart wrote:
Given that, I have to agree with Fernando that initialize is merely a superset of value_initialize and can be harder to explain unless it derives from value_initialize (even if it shares nothing from the base and only makes clear that it is a superset).
Thanks, Robert. But do you mean public inheritance? You know, I once considered having initialized<T> publicly derived from value_initialized<T>: http://lists.boost.org/Archives/boost/2010/03/164356.php But then I realized that it would imply that any "initialized" object is also a value_initialized object. While certainly an initialized object does not need to be value-initialized.
That is what I meant. A value_initialized object isn't stuck with its initialized value, is it? IOW, you can change the value later, at which point the object is no longer in a value-initialized state. Is that wrong? Is that a violation of the class' purpose? No. Likewise, an initialized instance allows for both forms of initialization; it is only concerned with some initialization having occurred. From value_initialized's standpoint, the object just has a value beyond what value-initialization would have given just as if an assignment had been done. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; 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.
participants (6)
-
Fernando Cacciola
-
Jeffrey Hellrung
-
Jeffrey Lee Hellrung, Jr.
-
Niels Dekker - address until 2010-10-10
-
Steven Watanabe
-
Stewart, Robert