Skip to content

Commit

Permalink
Added two new traits and a way to specify them
Browse files Browse the repository at this point in the history
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: [email protected]

FB internal diff: D610996
  • Loading branch information
Gownta authored and jdelong committed Dec 16, 2012
1 parent 291bf06 commit 93b0f54
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 5 deletions.
69 changes: 64 additions & 5 deletions folly/Traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@
#ifndef 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/mpl/and.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/not.hpp>
#include <memory>
#include <bits/c++config.h>

namespace folly {

Expand Down Expand Up @@ -57,9 +61,64 @@ namespace folly {
* types. You may want to add your own specializations. Do so in
* namespace folly and make sure you keep the specialization of
* 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

Expand All @@ -77,7 +136,7 @@ template <class T> struct IsRelocatable : boost::mpl::not_<boost::is_class<T> >
* FOLLY_ASSUME_RELOCATABLE(MyType<T1, T2>)
*/
#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
Expand Down
93 changes: 93 additions & 0 deletions folly/test/TraitsTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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();
}

0 comments on commit 93b0f54

Please sign in to comment.