id summary reporter owner description type status milestone component version severity resolution keywords cc 12002 optional(Expr&&) is insufficiently constrained akrzemi1 akrzemi1 "Hi, A user reported a bug (VSO#191303/Connect#2351203, see [1]) using Boost.Optional with MSVC 2015 Update 2. The original test case involved a minor bug in VC's tuple, which I'll look into fixing in the future (specifically, N-tuples recursively construct (N - 1)-tuples, in a way that's visible to overload resolution). However, there is also a bug in boost::optional. Here's a reduced test case, which contains the relevant parts of boost::optional, and doesn't involve that bug in VC's tuple: C:\Temp>type meow.cpp #include #include #include using namespace std; struct none_t { }; template struct optional { T thing; optional(none_t) : thing() { } template ::type, none_t>::value #ifdef FIX && is_constructible::value #endif >::type> explicit optional(Expr&& expr) : thing(forward(expr)) { } }; int main() { tuple one{}; tuple> two(one); } C:\Temp>cl /EHsc /nologo /W4 meow.cpp meow.cpp meow.cpp(22): error C2440: 'initializing': cannot convert from 'std::tuple' to 'double' [...context...] C:\Temp>cl /EHsc /nologo /W4 /DFIX meow.cpp meow.cpp C:\Temp> This is happening because I implemented N4387 (see [2]) and the Proposed Resolution for LWG 2549 (see [3]). The PR is required to implement N4387 safely. The direct-init of two from one is attempting to select tuple's converting copy ctor (which N4387 marks as implicit, because optional's constructor from none_t is implicit). However, LWG 2549 additionally constrains the converting copy ctor. In English, when the source is tuple and the destination is tuple, LWG 2549 determines whether A is constructible from tuple. If it IS, then the converting copy ctor vanishes, so that tuple's perfect forwarding ctor (tuple(UTypes&&...)) can construct A from tuple. Alternatively, if A ISN'T constructible from tuple, then the perfect forwarding ctor SFINAEs away while the converting copy ctor is permitted to participate, so A is constructed from the B within the tuple. The boost::optional bug is that optional(Expr&&) isn't sufficiently constrained, so it appears to be constructible (via is_constructible) from tuple, even though the definition will explode. So LWG 2549 makes tuple's converting copy ctor vanish, and we end up attempting to construct optional from tuple which is doomed. This is NOT a problem with LWG 2549's Proposed Resolution, NOR is it a problem in VC 2015 Update 2's tuple (which has correctly implemented this, at least for the 1-tuple case, as previously mentioned). The fix that should be applied to boost::optional is to constrain optional(Expr&&) based on whether its definition will compile. (This is inherently safe, because it just makes is_constructible report accurate answers, and doesn't affect code that previously compiled.) WG21 has (gradually) taught pair/tuple to do this (constructors are now constrained on is_constructible for elements, and additionally is_convertible when they care about implicitness; previously they didn't ask is_constructible). The relevant code in optional.hpp is: template explicit optional ( Expr&& expr, BOOST_DEDUCED_TYPENAME boost::disable_if_c< (boost::is_base_of::type>::value) || boost::is_same::type, none_t>::value >::type* = 0 ) : base(boost::forward(expr),boost::addressof(expr)) {optional_detail::prevent_binding_rvalue_ref_to_optional_lvalue_ref();} Unlike my reduced repro (where is_constructible is the constraint corresponding to thing(forward(expr))), I can't suggest an exact fix without knowing what optional_base's constructor is going to do with the provided arguments. As an aside, the ""prevent_binding"" stuff should probably be expressed as a SFINAE constraint, not a static_assert. Thanks, STL [1] https://connect.microsoft.com/VisualStudio/feedback/details/2351203/vc14-2-ctp1-std-tuple-broken [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4387.html [3] http://cplusplus.github.io/LWG/lwg-active.html#2549 " Feature Requests closed Boost 1.61.0 optional Boost 1.61.0 Problem fixed raad@… marci_r@…