Chromium Code Reviews| Index: third_party/WebKit/Source/wtf/TypeTraits.h |
| diff --git a/third_party/WebKit/Source/wtf/TypeTraits.h b/third_party/WebKit/Source/wtf/TypeTraits.h |
| index d3ef548876db6d540ac964845425393e9a94e19f..c6a052308bed20a8cb638c66d795995be912c78b 100644 |
| --- a/third_party/WebKit/Source/wtf/TypeTraits.h |
| +++ b/third_party/WebKit/Source/wtf/TypeTraits.h |
| @@ -48,19 +48,71 @@ enum WeakHandlingFlag { |
| WeakHandlingInCollections |
| }; |
| +// Compilers behave differently on __has_trivial_assign(T) if T has a user-deleted copy assignment operator: |
| +// |
| +// * MSVC returns false; but |
| +// * The others return true. |
| +// |
| +// To workaround that, here we have IsAssignable<T, From> class template, but unfortunately, MSVC 2013 cannot compile |
|
Nico
2016/10/01 19:34:45
is this still needed now that we're on 2015?
|
| +// it due to the lack of expression SFINAE. |
| +// |
| +// Thus, IsAssignable is only defined on non-MSVC compilers. |
| +#if !COMPILER(MSVC) || COMPILER(CLANG) |
| +template <typename T, typename From> |
| +class IsAssignable { |
| + typedef char YesType; |
| + struct NoType { |
| + char padding[8]; |
| + }; |
| + |
| + template <typename T2, typename From2, typename = decltype(std::declval<T2>() = std::declval<From2>())> |
| + static YesType checkAssignability(int); |
| + template <typename T2, typename From2> |
| + static NoType checkAssignability(...); |
| + |
| +public: |
| + static const bool value = sizeof(checkAssignability<T, From>(0)) == sizeof(YesType); |
| +}; |
| + |
| +template <typename T> |
| +struct IsCopyAssignable { |
| + static_assert(!std::is_reference<T>::value, "T must not be a reference."); |
| + static const bool value = IsAssignable<T, const T&>::value; |
| +}; |
| + |
| +template <typename T> |
| +struct IsMoveAssignable { |
| + static_assert(!std::is_reference<T>::value, "T must not be a reference."); |
| + static const bool value = IsAssignable<T, T&&>::value; |
| +}; |
| +#endif // !COMPILER(MSVC) || COMPILER(CLANG) |
| + |
| template <typename T> struct IsTriviallyCopyAssignable { |
| +#if COMPILER(MSVC) && !COMPILER(CLANG) |
| static const bool value = __has_trivial_assign(T); |
| +#else |
| + static const bool value = __has_trivial_assign(T) && IsCopyAssignable<T>::value; |
| +#endif |
| }; |
| template <typename T> struct IsTriviallyMoveAssignable { |
| - static const bool value = __has_trivial_assign(T); |
| + // TODO(yutak): This isn't really correct, because __has_trivial_assign appears to look only at copy assignment. |
| + // However, std::is_trivially_move_assignable isn't available at this moment, and there isn't a good way to |
| + // write that ourselves. |
| + // |
| + // Here we use IsTriviallyCopyAssignable as a conservative approximation: if T is trivially copy assignable, |
| + // T is trivially move assignable, too. This definition misses a case where T is trivially move-only assignable, |
| + // but such cases should be rare. |
| + static const bool value = IsTriviallyCopyAssignable<T>::value; |
| }; |
| template <typename T> struct IsTriviallyDefaultConstructible { |
| + // TODO(yutak): Below has the same issue as crbug.com/592767. |
| static const bool value = __has_trivial_constructor(T); |
| }; |
| template <typename T> struct IsTriviallyDestructible { |
| + // TODO(yutak): Ditto. |
| static const bool value = __has_trivial_destructor(T); |
| }; |