Commit 87e1985f authored by Tudor Bosman's avatar Tudor Bosman Committed by Jordan DeLong

fix Traits.md

Test Plan: looked at the generated html in a browser

Reviewed By: andrei.alexandrescu@fb.com

FB internal diff: D642998
parent 785dd995
'folly/Traits.h' 'folly/Traits.h'
----------------- -----------------
Implements traits complementary to those provided in <boost/type_traits.h> Implements traits complementary to those provided in <boost/type_traits.h>
* Implements `IsRelocatable` trait. * Implements `IsRelocatable` trait.
* Implements `IsOneOf` trait * Implements `IsOneOf` trait
* Macros to state the assumptions easily * Macros to state the assumptions easily
### Motivation ### Motivation
*** ***
<boost/type_traits.hpp> is the Boost type-traits library defining a
variety of traits such as `is_integral` or `is_floating_point`. This helps
to gain more information about a given type.
Many traits introduced by Boost have been standardized in C++11.
folly/Traits.h implements traits complementing those present in boost.
### IsRelocatable
***
In C++, the default way to move an object is by
calling the copy constructor and destroying the old copy
instead of directly copying the memory contents by using memcpy().
The conservative approach of moving an object assumes that the copied
object is not relocatable.
The two following code sequences should be semantically equivalent for a
relocatable type:
```Cpp
{
void conservativeMove(T * from, T * to) {
new(to) T(from);
(*from).~T();
}
}
{
void optimizedMove(T * from, T * to) {
memcpy(to, from, sizeof(T));
}
}
```
Very few C++ types are non-relocatable.
The type defined below maintains a pointer inside an embedded buffer and
hence would be non-relocatable. Moving the object by simply copying its
memory contents would leave the internal pointer pointing to the old buffer.
```Cpp
class NonRelocatableType {
private:
char buffer[1024];
char * pointerToBuffer;
...
public:
NonRelocatableType() : pointerToBuffer(buffer) {}
...
};
```
We can optimize the task of moving a relocatable type T using memcpy.
IsRelocatable<T>::value describes the ability of moving around memory
a value of type T by using memcpy.
### Usage
***
* Declaring types
```Cpp
template <class T1, class T2>
class MyParameterizedType;
class MySimpleType;
```
* Declaring a type as relocatable
Appending the lines below after definition of My*Type
(`MyParameterizedType` or `MySimpleType`) will declare it as relocatable
```Cpp
/* Definition of My*Type goes here */
// global namespace (not inside any namespace)
namespace folly {
// defining specialization of IsRelocatable for MySimpleType
template <>
struct IsRelocatable<MySimpleType> : boost::true_type {};
// defining specialization of IsRelocatable for MyParameterizedType
template <class T1, class T2>
struct IsRelocatable<MyParameterizedType<T1, T2>>
: ::boost::true_type {};
}
```
* To make it easy to state assumptions for a regular type or a family of `<boost/type_traits.hpp>` is the Boost type-traits library defining a
parameterized type, various macros can be used as shown below. variety of traits such as `is_integral` or `is_floating_point`. This helps
to gain more information about a given type.
Many traits introduced by Boost have been standardized in C++11.
* Stating that a type is Relocatable using a macro `folly/Traits.h` implements traits complementing those present in boost.
```Cpp
// global namespace
namespace folly {
// For a Regular Type
FOLLY_ASSUME_RELOCATABLE(MySimpleType);
// For a Parameterized Type
FOLLY_ASSUME_RELOCATABLE(MyParameterizedType<T1, T2>);
}
```
* Stating that a type has no throw constructor using a macro ### IsRelocatable
***
In C++, the default way to move an object is by
calling the copy constructor and destroying the old copy
instead of directly copying the memory contents by using memcpy().
The conservative approach of moving an object assumes that the copied
object is not relocatable.
The two following code sequences should be semantically equivalent for a
relocatable type:
```Cpp ```Cpp
namespace boost { {
// For a Regular Type void conservativeMove(T * from, T * to) {
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MySimpleType); new(to) T(from);
// For a Parameterized Type (*from).~T();
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyParameterizedType<T1, T2>);
} }
``` }
`fbvector` only works with relocatable objects. If assumptions are not stated {
explicitly, `fbvector<MySimpleType>` or `fbvector<MyParameterizedType>` void optimizedMove(T * from, T * to) {
will fail to compile due to assertion below: memcpy(to, from, sizeof(T));
}
```Cpp }
BOOST_STATIC_ASSERT( ```
IsRelocatable<My*Type>::value
); Very few C++ types are non-relocatable.
``` The type defined below maintains a pointer inside an embedded buffer and
hence would be non-relocatable. Moving the object by simply copying its
FOLLY_ASSUME_FBVECTOR_COMPATIBLE*(type) macros can be used to state that type memory contents would leave the internal pointer pointing to the old buffer.
is relocatable and has nothrow constructor.
```Cpp
* Stating that a type is `fbvector-compatible` using macros class NonRelocatableType {
i.e. relocatable and has nothrow default constructor private:
char buffer[1024];
```Cpp char * pointerToBuffer;
// at global level, i.e no namespace ...
// macro for regular type public:
FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MySimpleType); NonRelocatableType() : pointerToBuffer(buffer) {}
// macro for types having 2 template parameters (MyParameterizedType) ...
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyParameterizedType); };
``` ```
Similary, We can optimize the task of moving a relocatable type T using memcpy.
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(MyTypeHavingOneParameter) macro is IsRelocatable<T>::value describes the ability of moving around memory
for family of parameterized types having 1 parameter a value of type T by using memcpy.
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(MyTypeHavingThreeParameters) macro is
for family of parameterized types having 3 parameters ### Usage
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(MyTypeHavingFourParameters) macro is ***
for family of parameterized types having 4 parameters
* Declaring types
* Few common types, namely `std::basic_string`, `std::vector`, `std::list`,
`std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`, ```Cpp
`std::function`, `boost::shared_ptr` which are compatible with `fbvector` template <class T1, class T2>
are already instantiated and declared compatible with `fbvector`. class MyParameterizedType;
`fbvector` can be directly used with any of these C++ types.
class MySimpleType;
* `std::pair` can be safely assumed to be compatible with `fbvector` if both ```
of its components are.
* Declaring a type as relocatable
### IsOneOf
*** Appending the lines below after definition of My*Type
(`MyParameterizedType` or `MySimpleType`) will declare it as relocatable
boost::is_same<T1, T2>::value can be used to test if types of T1 and T2 are
same. folly::IsOneOf<T, T1, Ts...>::value can be used to test if type of T1 ```Cpp
matches the type of one of the other template parameter, T1, T2, ...Tn. /* Definition of My*Type goes here */
Recursion is used to implement this type trait. // global namespace (not inside any namespace)
namespace folly {
if boost::is_integral<T>::value == 1 and boost::is_integral<T2>::value == 1 // defining specialization of IsRelocatable for MySimpleType
then folly::IsOneOf<T, T1, T2, T3>::value will return 1 template <>
struct IsRelocatable<MySimpleType> : boost::true_type {};
// defining specialization of IsRelocatable for MyParameterizedType
template <class T1, class T2>
struct IsRelocatable<MyParameterizedType<T1, T2>>
: ::boost::true_type {};
}
```
* To make it easy to state assumptions for a regular type or a family of
parameterized type, various macros can be used as shown below.
* Stating that a type is Relocatable using a macro
```Cpp
// global namespace
namespace folly {
// For a Regular Type
FOLLY_ASSUME_RELOCATABLE(MySimpleType);
// For a Parameterized Type
FOLLY_ASSUME_RELOCATABLE(MyParameterizedType<T1, T2>);
}
```
* Stating that a type has no throw constructor using a macro
```Cpp
namespace boost {
// For a Regular Type
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MySimpleType);
// For a Parameterized Type
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyParameterizedType<T1, T2>);
}
```
`fbvector` only works with relocatable objects. If assumptions are not stated
explicitly, `fbvector<MySimpleType>` or `fbvector<MyParameterizedType>`
will fail to compile due to assertion below:
```Cpp
BOOST_STATIC_ASSERT(
IsRelocatable<My*Type>::value
);
```
FOLLY_ASSUME_FBVECTOR_COMPATIBLE*(type) macros can be used to state that type
is relocatable and has nothrow constructor.
* Stating that a type is `fbvector-compatible` using macros
i.e. relocatable and has nothrow default constructor
```Cpp
// at global level, i.e no namespace
// macro for regular type
FOLLY_ASSUME_FBVECTOR_COMPATIBLE(MySimpleType);
// macro for types having 2 template parameters (MyParameterizedType)
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(MyParameterizedType);
```
Similarly,
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(MyTypeHavingOneParameter) macro is
for family of parameterized types having 1 parameter
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(MyTypeHavingThreeParameters) macro is
for family of parameterized types having 3 parameters
* FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(MyTypeHavingFourParameters) macro is
for family of parameterized types having 4 parameters
Few common types, namely `std::basic_string`, `std::vector`, `std::list`,
`std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`,
`std::function`, `boost::shared_ptr` which are compatible with `fbvector` are
already instantiated and declared compatible with `fbvector`. `fbvector` can be
directly used with any of these C++ types.
`std::pair` can be safely assumed to be compatible with `fbvector` if both of
its components are.
### IsOneOf
***
`boost::is_same<T1, T2>::value` can be used to test if types of T1 and T2 are
same. `folly::IsOneOf<T, T1, Ts...>::value` can be used to test if type of T1
matches the type of one of the other template parameter, T1, T2, ...Tn.
Recursion is used to implement this type trait.
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