
Chris Hamilton wrote:
Caveat: There would be a small violation to the "Never Empty Guarantee" if a reference was the first templated type and the variant was default constructed; in this case, it would be default constructible (as internally it would be stored using a pointer), but the pointer would have a null value. Trying to use this value would cause an error, obviously.
Just forbid default construction in this case. It isn't very hard.
Okay. So, I dug into the variant source code to see how hard this would be to implement. In my mind, it came down to the following: (1) variant currently wraps reference types with reference_content<>. Instead, make it wrap them with reference_wrapper. (2) Replace all reference_content<> handling throughout variant with reference_wrapper<> handlers. (3) Make reference_wrapper support operator= (by removing the explicit from the constructors). reference_wrappers already forbid default construction, so the above (quoted discussion) is a non-issue. (4) Add second versions of the variant assign, constructor, etc, functions that can pass non-const references (so non-const reference types can be handled as variant input types). This now lets me do something like: // The reference type is the second one, so that this object // can be default constructible. typedef boost::variant<const char *, const std::string &> String; const char * s1 = "string1"; std::string s2("string2"); String s; // This doesn't throw s = s1; boost::get<const char *>(s); // Nor does this. s = s2; boost::get<const std::string&>(s); Anybody see the utility of this? (In my mind, this is a feature I want variants to have.) Anybody see any problems with the approach I've taken? I haven't run the entire variant test suite yet, nor have I explored all possible uses (and misuses) of reference types, but I would appreciate some early feedback. I've attached a unified patch (taken against boost-trunk). Cheers, Chris