https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105683
Jonathan Wakely <redi at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |DUPLICATE Status|UNCONFIRMED |RESOLVED --- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> --- Reduced: #include <vector> namespace ossia { struct value; struct value_variant_type { union Impl { std::vector<ossia::value> m_value8; Impl() { } ~Impl() { } } m_impl; value_variant_type() { } value_variant_type(const value_variant_type&) { } value_variant_type(const std::vector<ossia::value>& v); value_variant_type(std::vector<ossia::value>&& v); value_variant_type& operator=(const value_variant_type&) { return *this; } value_variant_type& operator=(value_variant_type&& other); }; struct value { value_variant_type v; value() { } value(const std::vector<ossia::value>& val) noexcept : v{val} { } explicit value(std::vector<ossia::value>&& val) noexcept : v{std::move(val)} { } }; inline value_variant_type::value_variant_type(const std::vector<ossia::value>& v) { new (&m_impl.m_value8) std::vector<ossia::value>{v}; } inline value_variant_type::value_variant_type(std::vector<ossia::value>&& v) { new (&m_impl.m_value8) std::vector<ossia::value>{std::move(v)}; } value_variant_type& value_variant_type::operator=(value_variant_type&& other) { new (&m_impl.m_value8) std::vector<ossia::value>{std::move(other.m_impl.m_value8)}; return *this; } inline ossia::value init_value() { return std::vector<ossia::value>{}; } void create_value_inline(ossia::value& v) { v = ossia::init_value(); } } int main() { ossia::value v; create_value_inline(v); } The problem is that you have vector<value>{val} where val can be converted to type value. The standard says that this should be interpreted as an initializer-list for the value elements of the vector (even though val is actually vector<value> and so you might copy construction). See PR 83264 for the relevant Core defect reports. My suggestion is to only use braced-init if you *really* want it, i.e. you are specifically trying to call an initializer-list constructor, or you *really* want narrowing checks. For a type like vector with an initializer-list constructor, and a value type that is constructible from everything under the sun (or like here, a specific set of types that includes the vector<value> type), using braced-init is more trouble than it's worth. It has no advantage, and serious disadvantages. Anybody who tells you to always used braced-init because it's superior is wrong. *** This bug has been marked as a duplicate of bug 83264 ***