https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95606

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
I think this is not a bug in GCC. A specialization of std::swap still depends
on the signature of the primary template, and that primary template requires
the argument types to be swappable. The is_swappable trait requires
move_constructible, and that requires complete types. Checking
is_move_constructible<json> will perform overload resolution which considers
the basic_json(json_ref) constructor, which tries to see if json_ref can be
constructed from a basic_json rvalue, which checks the constraint on the
json_ref constructor, which depends on basic_json, which is incomplete at this
point.

The json code is incorrect and should be fixed.

The std::swap<json> specialization is wrong and should be replaced by a normal
(non-template) overload in the same namespace as the json type:

void swap(json&, json&) noexcept;

The json_ref constructor should be constrained to avoid recursive
instantiations with incomplete types, e.g.

template<typename T, typename U>
  using is_not = std::is_same<std::remove_cv_t<std::remove_reference_t<T>>, U>;

class json_ref
{
  public:
    template <typename T,
              typename = std::enable_if_t<!is_not<T, json_ref>::value>,
              typename = std::enable_if_t<!is_not<T, json>::value>,
              bool = std::is_constructible<json, T>::value>
    json_ref(T &&){}
};

Reply via email to