Commit 61e32c4c authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Cut FOLLY_IS_TRIVIALLY_COPYABLE macro

Summary:
[Folly] Cut `FOLLY_IS_TRIVIALLY_COPYABLE` macro, replacing all uses with `folly::is_trivially_copyable`.

And cut `folly::IsTriviallyCopyable` with member-type-detection support, and move `folly::traits_detail::is_trivially_copyable` to `folly::is_trivially_copyable`.

`FOLLY_IS_TRIVIALLY_COPYABLE` and `folly::IsTriviallyCopyable` were there to support gcc < 5.

Reviewed By: Orvid

Differential Revision: D8246972

fbshipit-source-id: 8af9bbdbfac8671a61ebaa200dbfd2426a40d2eb
parent 101c87e4
...@@ -248,7 +248,7 @@ struct DoNotOptimizeAwayNeedsIndirect { ...@@ -248,7 +248,7 @@ struct DoNotOptimizeAwayNeedsIndirect {
// First two constraints ensure it can be an "r" operand. // First two constraints ensure it can be an "r" operand.
// std::is_pointer check is because callers seem to expect that // std::is_pointer check is because callers seem to expect that
// doNotOptimizeAway(&x) is equivalent to doNotOptimizeAway(x). // doNotOptimizeAway(&x) is equivalent to doNotOptimizeAway(x).
constexpr static bool value = !folly::IsTriviallyCopyable<Decayed>::value || constexpr static bool value = !folly::is_trivially_copyable<Decayed>::value ||
sizeof(Decayed) > sizeof(long) || std::is_pointer<Decayed>::value; sizeof(Decayed) > sizeof(long) || std::is_pointer<Decayed>::value;
}; };
} // namespace detail } // namespace detail
......
...@@ -168,7 +168,7 @@ enum class StorageType { ePODStruct, ePODUnion, eUnion }; ...@@ -168,7 +168,7 @@ enum class StorageType { ePODStruct, ePODUnion, eUnion };
template <class Value, class Error> template <class Value, class Error>
constexpr StorageType getStorageType() { constexpr StorageType getStorageType() {
return StrictAllOf<IsTriviallyCopyable, Value, Error>::value return StrictAllOf<is_trivially_copyable, Value, Error>::value
? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) && ? (sizeof(std::pair<Value, Error>) <= sizeof(void * [2]) &&
StrictAllOf<std::is_trivial, Value, Error>::value StrictAllOf<std::is_trivial, Value, Error>::value
? StorageType::ePODStruct ? StorageType::ePODStruct
...@@ -903,8 +903,6 @@ class Expected final : expected_detail::ExpectedStorage<Value, Error> { ...@@ -903,8 +903,6 @@ class Expected final : expected_detail::ExpectedStorage<Value, Error> {
public: public:
using value_type = Value; using value_type = Value;
using error_type = Error; using error_type = Error;
using IsTriviallyCopyable = typename expected_detail::
StrictAllOf<IsTriviallyCopyable, Value, Error>::type;
template <class U> template <class U>
using rebind = Expected<U, Error>; using rebind = Expected<U, Error>;
......
...@@ -208,10 +208,12 @@ class fbvector { ...@@ -208,10 +208,12 @@ class fbvector {
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
private: private:
typedef std::integral_constant<bool, typedef std::integral_constant<
IsTriviallyCopyable<T>::value && bool,
sizeof(T) <= 16 // don't force large structures to be passed by value is_trivially_copyable<T>::value &&
> should_pass_by_value; sizeof(T) <= 16 // don't force large structures to be passed by value
>
should_pass_by_value;
typedef typename std::conditional< typedef typename std::conditional<
should_pass_by_value::value, T, const T&>::type VT; should_pass_by_value::value, T, const T&>::type VT;
typedef typename std::conditional< typedef typename std::conditional<
...@@ -485,7 +487,7 @@ class fbvector { ...@@ -485,7 +487,7 @@ class fbvector {
template <typename It> template <typename It>
void D_uninitialized_copy_a(T* dest, It first, It last) { void D_uninitialized_copy_a(T* dest, It first, It last) {
if (usingStdAllocator::value) { if (usingStdAllocator::value) {
if (folly::IsTriviallyCopyable<T>::value) { if (folly::is_trivially_copyable<T>::value) {
S_uninitialized_copy_bits(dest, first, last); S_uninitialized_copy_bits(dest, first, last);
} else { } else {
S_uninitialized_copy(dest, first, last); S_uninitialized_copy(dest, first, last);
...@@ -570,7 +572,7 @@ class fbvector { ...@@ -570,7 +572,7 @@ class fbvector {
} }
static const T* S_copy_n(T* dest, const T* first, size_type n) { static const T* S_copy_n(T* dest, const T* first, size_type n) {
if (folly::IsTriviallyCopyable<T>::value) { if (is_trivially_copyable<T>::value) {
std::memcpy((void*)dest, (void*)first, n * sizeof(T)); std::memcpy((void*)dest, (void*)first, n * sizeof(T));
return first + n; return first + n;
} else { } else {
...@@ -580,7 +582,7 @@ class fbvector { ...@@ -580,7 +582,7 @@ class fbvector {
static std::move_iterator<T*> static std::move_iterator<T*>
S_copy_n(T* dest, std::move_iterator<T*> mIt, size_type n) { S_copy_n(T* dest, std::move_iterator<T*> mIt, size_type n) {
if (folly::IsTriviallyCopyable<T>::value) { if (is_trivially_copyable<T>::value) {
T* first = mIt.base(); T* first = mIt.base();
std::memcpy((void*)dest, (void*)first, n * sizeof(T)); std::memcpy((void*)dest, (void*)first, n * sizeof(T));
return std::make_move_iterator(first + n); return std::make_move_iterator(first + n);
......
...@@ -417,7 +417,6 @@ nobase_follyinclude_HEADERS = \ ...@@ -417,7 +417,6 @@ nobase_follyinclude_HEADERS = \
portability/SysTypes.h \ portability/SysTypes.h \
portability/SysUio.h \ portability/SysUio.h \
portability/Time.h \ portability/Time.h \
portability/TypeTraits.h \
portability/Unistd.h \ portability/Unistd.h \
portability/Windows.h \ portability/Windows.h \
Preprocessor.h \ Preprocessor.h \
......
...@@ -286,6 +286,19 @@ using type_t = typename traits_detail::type_t_<T, Ts...>::type; ...@@ -286,6 +286,19 @@ using type_t = typename traits_detail::type_t_<T, Ts...>::type;
template <class... Ts> template <class... Ts>
using void_t = type_t<void, Ts...>; using void_t = type_t<void, Ts...>;
// Older versions of libstdc++ do not provide std::is_trivially_copyable
#if defined(__clang__) && !defined(_LIBCPP_VERSION)
template <class T>
struct is_trivially_copyable
: std::integral_constant<bool, __is_trivially_copyable(T)> {};
#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
template <class T>
struct is_trivially_copyable : std::is_trivial<T> {};
#else
template <class T>
using is_trivially_copyable = std::is_trivially_copyable<T>;
#endif
/** /**
* IsRelocatable<T>::value describes the ability of moving around * IsRelocatable<T>::value describes the ability of moving around
* memory a value of type T by using memcpy (as opposed to the * memory a value of type T by using memcpy (as opposed to the
...@@ -323,11 +336,6 @@ using void_t = type_t<void, Ts...>; ...@@ -323,11 +336,6 @@ using void_t = type_t<void, Ts...>;
* *
* It may be unset in a base class by overriding the typedef to false_type. * It may be unset in a base class by overriding the typedef to false_type.
*/ */
/*
* IsTriviallyCopyable describes the value semantics property. C++11 contains
* the type trait is_trivially_copyable; however, it is not yet implemented
* in gcc (as of 4.7.1), and the user may wish to specify otherwise.
*/
/* /*
* IsZeroInitializable describes the property that default construction is the * IsZeroInitializable describes the property that default construction is the
* same as memset(dst, 0, sizeof(T)). * same as memset(dst, 0, sizeof(T)).
...@@ -347,22 +355,9 @@ namespace traits_detail { ...@@ -347,22 +355,9 @@ namespace traits_detail {
FOLLY_HAS_TRUE_XXX(IsRelocatable); FOLLY_HAS_TRUE_XXX(IsRelocatable);
FOLLY_HAS_TRUE_XXX(IsZeroInitializable); FOLLY_HAS_TRUE_XXX(IsZeroInitializable);
FOLLY_HAS_TRUE_XXX(IsTriviallyCopyable);
#undef FOLLY_HAS_TRUE_XXX #undef FOLLY_HAS_TRUE_XXX
// Older versions of libstdc++ do not provide std::is_trivially_copyable
#if defined(__clang__) && !defined(_LIBCPP_VERSION)
template <class T>
struct is_trivially_copyable
: std::integral_constant<bool, __is_trivially_copyable(T)> {};
#elif defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
template <class T>
struct is_trivially_copyable : std::is_trivial<T> {};
#else
template <class T>
using is_trivially_copyable = std::is_trivially_copyable<T>;
#endif
} // namespace traits_detail } // namespace traits_detail
struct Ignore { struct Ignore {
...@@ -431,21 +426,14 @@ struct IsNothrowSwappable ...@@ -431,21 +426,14 @@ struct IsNothrowSwappable
/* using override */ using traits_detail_IsNothrowSwappable::IsNothrowSwappable; /* using override */ using traits_detail_IsNothrowSwappable::IsNothrowSwappable;
template <class T> struct IsTriviallyCopyable template <class T>
: std::conditional< struct IsRelocatable : std::conditional<
traits_detail::has_IsTriviallyCopyable<T>::value, traits_detail::has_IsRelocatable<T>::value,
traits_detail::has_true_IsTriviallyCopyable<T>, traits_detail::has_true_IsRelocatable<T>,
traits_detail::is_trivially_copyable<T> // TODO add this line (and some tests for it) when we
>::type {}; // upgrade to gcc 4.7
// std::is_trivially_move_constructible<T>::value ||
template <class T> struct IsRelocatable is_trivially_copyable<T>>::type {};
: std::conditional<
traits_detail::has_IsRelocatable<T>::value,
traits_detail::has_true_IsRelocatable<T>,
// TODO add this line (and some tests for it) when we upgrade to gcc 4.7
//std::is_trivially_move_constructible<T>::value ||
IsTriviallyCopyable<T>
>::type {};
template <class T> struct IsZeroInitializable template <class T> struct IsZeroInitializable
: std::conditional< : std::conditional<
......
...@@ -921,7 +921,7 @@ class VectorContainerPolicy : public BasePolicy< ...@@ -921,7 +921,7 @@ class VectorContainerPolicy : public BasePolicy<
return folly::AllocatorHasDefaultObjectConstruct<Alloc, Value, Value>:: return folly::AllocatorHasDefaultObjectConstruct<Alloc, Value, Value>::
value && value &&
folly::AllocatorHasDefaultObjectDestroy<Alloc, Value>::value && folly::AllocatorHasDefaultObjectDestroy<Alloc, Value>::value &&
FOLLY_IS_TRIVIALLY_COPYABLE(Value); folly::is_trivially_copyable<Value>::value;
} }
public: public:
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#include <folly/lang/Launder.h> #include <folly/lang/Launder.h>
#include <folly/lang/SafeAssert.h> #include <folly/lang/SafeAssert.h>
#include <folly/portability/Builtins.h> #include <folly/portability/Builtins.h>
#include <folly/portability/TypeTraits.h>
#include <folly/container/detail/F14Defaults.h> #include <folly/container/detail/F14Defaults.h>
#include <folly/container/detail/F14IntrinsicsAvailability.h> #include <folly/container/detail/F14IntrinsicsAvailability.h>
...@@ -1379,8 +1378,8 @@ class F14Table : public Policy { ...@@ -1379,8 +1378,8 @@ class F14Table : public Policy {
// partial failure should not occur. Sorry for the subtle invariants // partial failure should not occur. Sorry for the subtle invariants
// in the Policy API. // in the Policy API.
if (FOLLY_IS_TRIVIALLY_COPYABLE(Item) && !this->destroyItemOnClear() && if (folly::is_trivially_copyable<Item>::value &&
bucket_count() == src.bucket_count()) { !this->destroyItemOnClear() && bucket_count() == src.bucket_count()) {
// most happy path // most happy path
auto n = allocSize(chunkMask_ + 1, bucket_count()); auto n = allocSize(chunkMask_ + 1, bucket_count());
std::memcpy(&chunks_[0], &src.chunks_[0], n); std::memcpy(&chunks_[0], &src.chunks_[0], n);
......
...@@ -25,8 +25,8 @@ ...@@ -25,8 +25,8 @@
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Traits.h>
#include <folly/detail/TurnSequencer.h> #include <folly/detail/TurnSequencer.h>
#include <folly/portability/TypeTraits.h>
#include <folly/portability/Unistd.h> #include <folly/portability/Unistd.h>
namespace folly { namespace folly {
...@@ -62,7 +62,7 @@ class LockFreeRingBuffer: boost::noncopyable { ...@@ -62,7 +62,7 @@ class LockFreeRingBuffer: boost::noncopyable {
"Element type must be nothrow default constructible"); "Element type must be nothrow default constructible");
static_assert( static_assert(
FOLLY_IS_TRIVIALLY_COPYABLE(T), folly::is_trivially_copyable<T>::value,
"Element type must be trivially copyable"); "Element type must be trivially copyable");
public: public:
......
...@@ -633,10 +633,12 @@ TEST(Collect, collectNParallel) { ...@@ -633,10 +633,12 @@ TEST(Collect, collectNParallel) {
/// Ensure that we can compile collectAll/Any with folly::small_vector /// Ensure that we can compile collectAll/Any with folly::small_vector
TEST(Collect, smallVector) { TEST(Collect, smallVector) {
static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<Unit>), static_assert(
"Futures should not be trivially copyable"); !folly::is_trivially_copyable<Future<Unit>>::value,
static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>), "Futures should not be trivially copyable");
"Futures should not be trivially copyable"); static_assert(
!folly::is_trivially_copyable<Future<int>>::value,
"Futures should not be trivially copyable");
{ {
folly::small_vector<Future<Unit>> futures; folly::small_vector<Future<Unit>> futures;
......
/*
* Copyright 2016-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
// Unfortunately, boost::has_trivial_copy<T> is broken in libc++ due to its
// usage of __has_trivial_copy(), so we can't use it as a
// least-common-denominator for C++11 implementations that don't support
// std::is_trivially_copyable<T>.
//
// http://stackoverflow.com/questions/12754886/has-trivial-copy-behaves-differently-in-clang-and-gcc-whos-right
//
// As a result, use std::is_trivially_copyable() where it exists, and fall back
// to Boost otherwise.
#if FOLLY_HAVE_STD__IS_TRIVIALLY_COPYABLE
#include <type_traits>
#define FOLLY_IS_TRIVIALLY_COPYABLE(T) (std::is_trivially_copyable<T>::value)
#else
#include <boost/type_traits.hpp>
#define FOLLY_IS_TRIVIALLY_COPYABLE(T) \
(boost::has_trivial_copy<T>::value && boost::has_trivial_destructor<T>::value)
#endif
...@@ -52,7 +52,6 @@ ...@@ -52,7 +52,6 @@
#include <folly/lang/Exception.h> #include <folly/lang/Exception.h>
#include <folly/memory/Malloc.h> #include <folly/memory/Malloc.h>
#include <folly/portability/Malloc.h> #include <folly/portability/Malloc.h>
#include <folly/portability/TypeTraits.h>
#if (FOLLY_X64 || FOLLY_PPC64) #if (FOLLY_X64 || FOLLY_PPC64)
#define FOLLY_SV_PACK_ATTR FOLLY_PACK_ATTR #define FOLLY_SV_PACK_ATTR FOLLY_PACK_ATTR
...@@ -102,7 +101,7 @@ namespace detail { ...@@ -102,7 +101,7 @@ namespace detail {
* memory is initialized to type T already. * memory is initialized to type T already.
*/ */
template <class T> template <class T>
typename std::enable_if<!FOLLY_IS_TRIVIALLY_COPYABLE(T)>::type typename std::enable_if<!folly::is_trivially_copyable<T>::value>::type
moveObjectsRight(T* first, T* lastConstructed, T* realLast) { moveObjectsRight(T* first, T* lastConstructed, T* realLast) {
if (lastConstructed == realLast) { if (lastConstructed == realLast) {
return; return;
...@@ -139,7 +138,7 @@ moveObjectsRight(T* first, T* lastConstructed, T* realLast) { ...@@ -139,7 +138,7 @@ moveObjectsRight(T* first, T* lastConstructed, T* realLast) {
// std::move_backward here will just turn into a memmove. (TODO: // std::move_backward here will just turn into a memmove. (TODO:
// change to std::is_trivially_copyable when that works.) // change to std::is_trivially_copyable when that works.)
template <class T> template <class T>
typename std::enable_if<FOLLY_IS_TRIVIALLY_COPYABLE(T)>::type typename std::enable_if<folly::is_trivially_copyable<T>::value>::type
moveObjectsRight(T* first, T* lastConstructed, T* realLast) { moveObjectsRight(T* first, T* lastConstructed, T* realLast) {
std::move_backward(first, lastConstructed, realLast); std::move_backward(first, lastConstructed, realLast);
} }
...@@ -222,7 +221,7 @@ struct IntegralSizePolicy<SizeType, true> ...@@ -222,7 +221,7 @@ struct IntegralSizePolicy<SizeType, true>
* ranges don't overlap. * ranges don't overlap.
*/ */
template <class T> template <class T>
typename std::enable_if<!FOLLY_IS_TRIVIALLY_COPYABLE(T)>::type typename std::enable_if<!folly::is_trivially_copyable<T>::value>::type
moveToUninitialized(T* first, T* last, T* out) { moveToUninitialized(T* first, T* last, T* out) {
std::size_t idx = 0; std::size_t idx = 0;
try { try {
...@@ -244,7 +243,7 @@ struct IntegralSizePolicy<SizeType, true> ...@@ -244,7 +243,7 @@ struct IntegralSizePolicy<SizeType, true>
// Specialization for trivially copyable types. // Specialization for trivially copyable types.
template <class T> template <class T>
typename std::enable_if<FOLLY_IS_TRIVIALLY_COPYABLE(T)>::type typename std::enable_if<folly::is_trivially_copyable<T>::value>::type
moveToUninitialized(T* first, T* last, T* out) { moveToUninitialized(T* first, T* last, T* out) {
std::memmove(out, first, (last - first) * sizeof *first); std::memmove(out, first, (last - first) * sizeof *first);
} }
......
...@@ -59,7 +59,7 @@ class AtomicStruct { ...@@ -59,7 +59,7 @@ class AtomicStruct {
static_assert(alignof(T) <= alignof(Raw), "underlying type is under-aligned"); static_assert(alignof(T) <= alignof(Raw), "underlying type is under-aligned");
static_assert(sizeof(T) <= sizeof(Raw), "underlying type is under-sized"); static_assert(sizeof(T) <= sizeof(Raw), "underlying type is under-sized");
static_assert( static_assert(
std::is_trivial<T>::value || folly::IsTriviallyCopyable<T>::value, std::is_trivial<T>::value || is_trivially_copyable<T>::value,
"target type must be trivially copyable"); "target type must be trivially copyable");
Atom<Raw> data; Atom<Raw> data;
......
...@@ -50,7 +50,7 @@ class Tearable { ...@@ -50,7 +50,7 @@ class Tearable {
// We memcpy the object representation, and the destructor would not know how // We memcpy the object representation, and the destructor would not know how
// to deal with an object state it doesn't understand. // to deal with an object state it doesn't understand.
static_assert( static_assert(
IsTriviallyCopyable<T>::value, is_trivially_copyable<T>::value,
"Tearable types must be trivially copyable."); "Tearable types must be trivially copyable.");
Tearable() = default; Tearable() = default;
......
...@@ -26,8 +26,6 @@ using namespace folly; ...@@ -26,8 +26,6 @@ using namespace folly;
namespace { namespace {
struct Data { struct Data {
using IsTriviallyCopyable = std::true_type;
Data(unsigned char value) { Data(unsigned char value) {
setValue(value); setValue(value);
} }
...@@ -54,6 +52,7 @@ struct Data { ...@@ -54,6 +52,7 @@ struct Data {
// sanitizers. // sanitizers.
unsigned char contents[99]; unsigned char contents[99];
}; };
static_assert(is_trivially_copyable<Data>::value, "not trivially-copyable");
TEST(TearableTest, BasicOperations) { TEST(TearableTest, BasicOperations) {
Tearable<Data> tearable; Tearable<Data> tearable;
......
...@@ -615,26 +615,26 @@ struct WithConstructor { ...@@ -615,26 +615,26 @@ struct WithConstructor {
TEST(Expected, TriviallyCopyable) { TEST(Expected, TriviallyCopyable) {
// These could all be static_asserts but EXPECT_* give much nicer output on // These could all be static_asserts but EXPECT_* give much nicer output on
// failure. // failure.
EXPECT_TRUE((IsTriviallyCopyable<Expected<int, E>>::value)); EXPECT_TRUE((is_trivially_copyable<Expected<int, E>>::value));
EXPECT_TRUE((IsTriviallyCopyable<Expected<char*, E>>::value)); EXPECT_TRUE((is_trivially_copyable<Expected<char*, E>>::value));
EXPECT_TRUE( EXPECT_TRUE(
(IsTriviallyCopyable<Expected<NoDestructor, E>>::value)); (is_trivially_copyable<Expected<NoDestructor, E>>::value));
EXPECT_FALSE( EXPECT_FALSE(
(IsTriviallyCopyable<Expected<WithDestructor, E>>::value)); (is_trivially_copyable<Expected<WithDestructor, E>>::value));
EXPECT_TRUE( EXPECT_TRUE(
(IsTriviallyCopyable<Expected<NoConstructor, E>>::value)); (is_trivially_copyable<Expected<NoConstructor, E>>::value));
EXPECT_FALSE( EXPECT_FALSE(
(IsTriviallyCopyable<Expected<std::string, E>>::value)); (is_trivially_copyable<Expected<std::string, E>>::value));
EXPECT_FALSE( EXPECT_FALSE(
(IsTriviallyCopyable<Expected<int, std::string>>::value)); (is_trivially_copyable<Expected<int, std::string>>::value));
// libstdc++ with GCC 4.x doesn't have std::is_trivially_copyable // libstdc++ with GCC 4.x doesn't have std::is_trivially_copyable
#if (defined(__clang__) && !defined(_LIBCPP_VERSION)) || \ #if (defined(__clang__) && !defined(_LIBCPP_VERSION)) || \
!(defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5) !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5)
EXPECT_TRUE( EXPECT_TRUE(
(IsTriviallyCopyable<Expected<WithConstructor, E>>::value)); (is_trivially_copyable<Expected<WithConstructor, E>>::value));
#endif #endif
EXPECT_TRUE( EXPECT_TRUE(
(IsTriviallyCopyable<Expected<Expected<int, E>, E>>::value)); (is_trivially_copyable<Expected<Expected<int, E>, E>>::value));
} }
TEST(Expected, Then) { TEST(Expected, Then) {
......
...@@ -48,7 +48,6 @@ TEST(Traits, has_member_type) { ...@@ -48,7 +48,6 @@ TEST(Traits, has_member_type) {
struct T1 {}; // old-style IsRelocatable, below struct T1 {}; // old-style IsRelocatable, below
struct T2 {}; // old-style IsRelocatable, below struct T2 {}; // old-style IsRelocatable, below
struct T3 { typedef std::true_type IsRelocatable; }; struct T3 { typedef std::true_type IsRelocatable; };
struct T4 { typedef std::true_type IsTriviallyCopyable; };
struct T5 : T3 {}; struct T5 : T3 {};
struct F1 {}; struct F1 {};
...@@ -93,14 +92,7 @@ TEST(Traits, unset) { ...@@ -93,14 +92,7 @@ TEST(Traits, unset) {
EXPECT_TRUE(IsRelocatable<F4>::value); EXPECT_TRUE(IsRelocatable<F4>::value);
} }
TEST(Traits, bitprop) {
EXPECT_TRUE(IsTriviallyCopyable<T4>::value);
EXPECT_TRUE(IsRelocatable<T4>::value);
}
TEST(Traits, bitAndInit) { TEST(Traits, bitAndInit) {
EXPECT_TRUE (IsTriviallyCopyable<int>::value);
EXPECT_FALSE(IsTriviallyCopyable<vector<int>>::value);
EXPECT_TRUE (IsZeroInitializable<int>::value); EXPECT_TRUE (IsZeroInitializable<int>::value);
EXPECT_FALSE(IsZeroInitializable<vector<int>>::value); EXPECT_FALSE(IsZeroInitializable<vector<int>>::value);
} }
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <folly/Conv.h> #include <folly/Conv.h>
#include <folly/Traits.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
#include <folly/portability/TypeTraits.h>
using folly::small_vector; using folly::small_vector;
using namespace folly::small_vector_policy; using namespace folly::small_vector_policy;
...@@ -70,8 +70,9 @@ static_assert(sizeof(small_vector<int16_t,4,uint16_t>) == 10, ...@@ -70,8 +70,9 @@ static_assert(sizeof(small_vector<int16_t,4,uint16_t>) == 10,
#endif #endif
static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(std::unique_ptr<int>), static_assert(
"std::unique_ptr<> is trivially copyable"); !folly::is_trivially_copyable<std::unique_ptr<int>>::value,
"std::unique_ptr<> is trivially copyable");
static_assert( static_assert(
alignof(small_vector<std::aligned_storage<32, 32>::type, 4>) == 32, alignof(small_vector<std::aligned_storage<32, 32>::type, 4>) == 32,
...@@ -133,8 +134,9 @@ struct NontrivialType { ...@@ -133,8 +134,9 @@ struct NontrivialType {
int32_t a; int32_t a;
}; };
static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(NontrivialType), static_assert(
"NontrivialType is trivially copyable"); !folly::is_trivially_copyable<NontrivialType>::value,
"NontrivialType is trivially copyable");
int NontrivialType::ctored = 0; int NontrivialType::ctored = 0;
...@@ -197,8 +199,9 @@ struct NoncopyableCounter { ...@@ -197,8 +199,9 @@ struct NoncopyableCounter {
}; };
int NoncopyableCounter::alive = 0; int NoncopyableCounter::alive = 0;
static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(NoncopyableCounter), static_assert(
"NoncopyableCounter is trivially copyable"); !folly::is_trivially_copyable<NoncopyableCounter>::value,
"NoncopyableCounter is trivially copyable");
// Check that throws don't break the basic guarantee for some cases. // Check that throws don't break the basic guarantee for some cases.
// Uses the method for testing exception safety described at // Uses the method for testing exception safety described at
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment