Commit 93b0f543 authored by Nicholas Ormrod's avatar Nicholas Ormrod Committed by Jordan DeLong

Added two new traits and a way to specify them

Summary:
Added IsBits (has value semantics; can be copied by memcpy and
deleted by free. Implies IsRelocatable) and Is0Initializable (new (ptr)
T() is equivalent to memset(ptr, 0, sizeof(T))).
Converted the boost types for IsRelocatable to std types (now available
from <type_traits>).
Added a new way to specify IsRelocatable, IsBits, and Is0Initializable:
typedef std::true_type <property-name> in your class. No namespace
exiting required. This method also supports inheritance, and may be
overriden in base classes.
Added a test file to test Traits.

Test Plan:
Run new test file. Compile some real-world code (in my case,
multifeed).

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D610996
parent 291bf062
...@@ -19,11 +19,15 @@ ...@@ -19,11 +19,15 @@
#ifndef FOLLY_BASE_TRAITS_H_ #ifndef FOLLY_BASE_TRAITS_H_
#define FOLLY_BASE_TRAITS_H_ #define FOLLY_BASE_TRAITS_H_
#include <memory>
#include <type_traits>
#include <bits/c++config.h>
#include <boost/type_traits.hpp> #include <boost/type_traits.hpp>
#include <boost/mpl/and.hpp> #include <boost/mpl/and.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/not.hpp> #include <boost/mpl/not.hpp>
#include <memory>
#include <bits/c++config.h>
namespace folly { namespace folly {
...@@ -57,9 +61,64 @@ namespace folly { ...@@ -57,9 +61,64 @@ namespace folly {
* types. You may want to add your own specializations. Do so in * types. You may want to add your own specializations. Do so in
* namespace folly and make sure you keep the specialization of * namespace folly and make sure you keep the specialization of
* IsRelocatable<SomeStruct> in the same header as SomeStruct. * IsRelocatable<SomeStruct> in the same header as SomeStruct.
*
* You may also declare a type to be relocatable by including
* `typedef std::true_type IsRelocatable;`
* in the class header.
*
* 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.
*/ */
template <class T> struct IsRelocatable : boost::mpl::not_<boost::is_class<T> > /*
{}; * IsZeroInitializable describes the property that default construction is the
* same as memset(dst, 0, sizeof(T)).
*/
namespace traits_detail {
#define FOLLY_HAS_TRUE_XXX(name) \
BOOST_MPL_HAS_XXX_TRAIT_DEF(name); \
template <class T> struct name ## _is_true \
: std::is_same<typename T::name, std::true_type> {}; \
template <class T> struct has_true_ ## name \
: std::conditional< \
has_ ## name <T>::value, \
name ## _is_true<T>, \
std::false_type \
>:: type {};
FOLLY_HAS_TRUE_XXX(IsRelocatable)
FOLLY_HAS_TRUE_XXX(IsZeroInitializable)
FOLLY_HAS_TRUE_XXX(IsTriviallyCopyable)
#undef FOLLY_HAS_TRUE_XXX
}
template <class T> struct IsTriviallyCopyable
: std::integral_constant<bool,
!std::is_class<T>::value ||
// TODO: add alternate clause is_trivially_copyable, when available
traits_detail::has_true_IsTriviallyCopyable<T>::value
> {};
template <class T> struct IsRelocatable
: std::integral_constant<bool,
!std::is_class<T>::value ||
// 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>::value ||
traits_detail::has_true_IsRelocatable<T>::value
> {};
template <class T> struct IsZeroInitializable
: std::integral_constant<bool,
!std::is_class<T>::value ||
traits_detail::has_true_IsZeroInitializable<T>::value
> {};
} // namespace folly } // namespace folly
...@@ -77,7 +136,7 @@ template <class T> struct IsRelocatable : boost::mpl::not_<boost::is_class<T> > ...@@ -77,7 +136,7 @@ template <class T> struct IsRelocatable : boost::mpl::not_<boost::is_class<T> >
* FOLLY_ASSUME_RELOCATABLE(MyType<T1, T2>) * FOLLY_ASSUME_RELOCATABLE(MyType<T1, T2>)
*/ */
#define FOLLY_ASSUME_RELOCATABLE(...) \ #define FOLLY_ASSUME_RELOCATABLE(...) \
struct IsRelocatable< __VA_ARGS__ > : ::boost::true_type {}; struct IsRelocatable< __VA_ARGS__ > : std::true_type {};
/** /**
* Use this macro ONLY inside namespace boost. When using it with a * Use this macro ONLY inside namespace boost. When using it with a
......
/*
* Copyright 2012 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.
*/
#include "folly/Benchmark.h"
#include "folly/Traits.h"
#include <gflags/gflags.h>
#include <gtest/gtest.h>
using namespace folly;
using namespace std;
struct T1 {}; // old-style IsRelocatable, below
struct T2 {}; // old-style IsRelocatable, below
struct T3 { typedef std::true_type IsRelocatable; };
struct T4 { typedef std::true_type IsTriviallyCopyable; };
struct T5 : T3 {};
struct F1 {};
struct F2 { typedef int IsRelocatable; };
struct F3 : T3 { typedef std::false_type IsRelocatable; };
struct F4 : T1 {};
namespace folly {
template <> struct IsRelocatable<T1> : std::true_type {};
template <> FOLLY_ASSUME_RELOCATABLE(T2);
}
TEST(Traits, scalars) {
EXPECT_TRUE(IsRelocatable<int>::value);
EXPECT_TRUE(IsRelocatable<bool>::value);
EXPECT_TRUE(IsRelocatable<double>::value);
EXPECT_TRUE(IsRelocatable<void*>::value);
}
TEST(Traits, containers) {
EXPECT_TRUE (IsRelocatable<vector<F1>>::value);
EXPECT_FALSE((IsRelocatable<pair<F1, F1>>::value));
EXPECT_TRUE ((IsRelocatable<pair<T1, T2>>::value));
EXPECT_TRUE (IsRelocatable<set<F1>>::value);
}
TEST(Traits, original) {
EXPECT_TRUE(IsRelocatable<T1>::value);
EXPECT_TRUE(IsRelocatable<T2>::value);
}
TEST(Traits, typedefd) {
EXPECT_TRUE (IsRelocatable<T3>::value);
EXPECT_TRUE (IsRelocatable<T5>::value);
EXPECT_FALSE(IsRelocatable<F2>::value);
EXPECT_FALSE(IsRelocatable<F3>::value);
}
TEST(Traits, unset) {
EXPECT_FALSE(IsRelocatable<F1>::value);
EXPECT_FALSE(IsRelocatable<F4>::value);
}
TEST(Traits, bitprop) {
EXPECT_TRUE(IsTriviallyCopyable<T4>::value);
EXPECT_TRUE(IsRelocatable<T4>::value);
}
TEST(Traits, bitAndInit) {
EXPECT_TRUE (IsTriviallyCopyable<int>::value);
EXPECT_FALSE(IsTriviallyCopyable<vector<int>>::value);
EXPECT_TRUE (IsZeroInitializable<int>::value);
EXPECT_FALSE(IsZeroInitializable<vector<int>>::value);
}
int main(int argc, char ** argv) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);
if (FLAGS_benchmark) {
folly::runBenchmarks();
}
return RUN_ALL_TESTS();
}
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