Skip to content

Commit e4f7a54

Browse files
laramielcopybara-github
authored andcommitted
In MSVC 17.14.x, without this, IntrusivePtr does not always call the correct copy/move operators. This seems like the type of compiler bug to break other users, however this workaround is pretty straight forward. Fixes: #242 PiperOrigin-RevId: 788650997 Change-Id: I3f731c8ffb098ce3042ec904346d73925dd3a7b9
1 parent 098b790 commit e4f7a54

File tree

1 file changed

+28
-8
lines changed

1 file changed

+28
-8
lines changed

tensorstore/internal/intrusive_ptr.h

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -356,14 +356,24 @@ class IntrusivePtr {
356356
return *this;
357357
}
358358

359+
/// Copy constructs from `rhs` which is an IntrusivePtr of a convertible type.
360+
/// If `rhs` is not null, acquires a new reference to `rhs.get()` by calling
361+
/// `R::increment(rhs.get())`.
359362
template <typename U,
360-
std::enable_if_t<std::is_convertible_v<
361-
typename R::template pointer<U>, pointer>>* = nullptr>
363+
std::enable_if_t<
364+
// https://developercommunity.visualstudio.com/t/10939927
365+
!std::is_same_v<T, U> &&
366+
std::is_convertible_v<typename R::template pointer<U>,
367+
pointer>>* = nullptr>
362368
IntrusivePtr(const IntrusivePtr<U, R>& rhs) noexcept
363369
: IntrusivePtr(rhs.get(), acquire_object_ref) {}
364370

365-
template <typename U, typename = std::enable_if_t<std::is_convertible_v<
366-
typename R::template pointer<U>, pointer>>>
371+
template <
372+
typename U,
373+
typename = std::enable_if_t<
374+
// https://developercommunity.visualstudio.com/t/10939927
375+
!std::is_same_v<T, U> &&
376+
std::is_convertible_v<typename R::template pointer<U>, pointer>>>
367377
IntrusivePtr& operator=(const IntrusivePtr<U, R>& rhs) noexcept {
368378
IntrusivePtr(rhs).swap(*this);
369379
return *this;
@@ -379,14 +389,24 @@ class IntrusivePtr {
379389
return *this;
380390
}
381391

392+
/// Move constructs from `rhs` which is an IntrusivePtr of a convertible type.
393+
/// If `rhs` is not null, transfers ownership of
394+
/// a reference from `rhs` to `*this`.
382395
template <typename U,
383-
std::enable_if_t<std::is_convertible_v<
384-
typename R::template pointer<U>, pointer>>* = nullptr>
396+
std::enable_if_t<
397+
// https://developercommunity.visualstudio.com/t/10939927
398+
!std::is_same_v<T, U> &&
399+
std::is_convertible_v<typename R::template pointer<U>,
400+
pointer>>* = nullptr>
385401
constexpr IntrusivePtr(IntrusivePtr<U, R>&& rhs) noexcept
386402
: IntrusivePtr(rhs.release(), adopt_object_ref) {}
387403

388-
template <typename U, typename = std::enable_if_t<std::is_convertible_v<
389-
typename R::template pointer<U>, pointer>>>
404+
template <
405+
typename U,
406+
typename = std::enable_if_t<
407+
// https://developercommunity.visualstudio.com/t/10939927
408+
!std::is_same_v<T, U> &&
409+
std::is_convertible_v<typename R::template pointer<U>, pointer>>>
390410
constexpr IntrusivePtr& operator=(IntrusivePtr<U, R>&& rhs) noexcept {
391411
IntrusivePtr(std::move(rhs)).swap(*this);
392412
return *this;

0 commit comments

Comments
 (0)