Commit 821c5d75 authored by Sarang Masti's avatar Sarang Masti Committed by Ajit Banerjee

Allow conversion from a type T to itself

Summary: same as title

Test Plan: - fbconfig -r folly && fbmake runtests

Reviewed By: andrei.alexandrescu@fb.com

Subscribers: folly-diffs@

FB internal diff: D1754577

Signature: t1:1754577:1419618119:4c1a59cd19b23de9a9f6574341944e5e80530d62
parent 450fee03
...@@ -53,6 +53,22 @@ ...@@ -53,6 +53,22 @@
namespace folly { namespace folly {
/**
* The identity conversion function.
* to<T>(T) returns itself for all types T.
*/
template <class Tgt, class Src>
typename std::enable_if<std::is_same<Tgt, Src>::value, Tgt>::type
to(const Src & value) {
return value;
}
template <class Tgt, class Src>
typename std::enable_if<std::is_same<Tgt, Src>::value, Tgt>::type
to(Src && value) {
return std::move(value);
}
/******************************************************************************* /*******************************************************************************
* Integral to integral * Integral to integral
******************************************************************************/ ******************************************************************************/
...@@ -64,7 +80,9 @@ namespace folly { ...@@ -64,7 +80,9 @@ namespace folly {
*/ */
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if< typename std::enable_if<
std::is_integral<Src>::value && std::is_integral<Tgt>::value, std::is_integral<Src>::value
&& std::is_integral<Tgt>::value
&& !std::is_same<Tgt, Src>::value,
Tgt>::type Tgt>::type
to(const Src & value) { to(const Src & value) {
/* static */ if (std::numeric_limits<Tgt>::max() /* static */ if (std::numeric_limits<Tgt>::max()
...@@ -90,7 +108,9 @@ to(const Src & value) { ...@@ -90,7 +108,9 @@ to(const Src & value) {
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if< typename std::enable_if<
std::is_floating_point<Tgt>::value && std::is_floating_point<Src>::value, std::is_floating_point<Tgt>::value
&& std::is_floating_point<Src>::value
&& !std::is_same<Tgt, Src>::value,
Tgt>::type Tgt>::type
to(const Src & value) { to(const Src & value) {
/* static */ if (std::numeric_limits<Tgt>::max() < /* static */ if (std::numeric_limits<Tgt>::max() <
...@@ -819,20 +839,6 @@ toAppendDelimFit(const Delimiter& delim, const Ts&... vs) { ...@@ -819,20 +839,6 @@ toAppendDelimFit(const Delimiter& delim, const Ts&... vs) {
template <class De, class Ts> template <class De, class Ts>
void toAppendDelimFit(const De&, const Ts&) {} void toAppendDelimFit(const De&, const Ts&) {}
/**
* to<SomeString>(SomeString str) or to<StringPiece>(StringPiece str) returns
* itself. As both std::string and folly::fbstring use Copy-on-Write, it's much
* more efficient by avoiding copying the underlying char array.
*/
template <class Tgt, class Src>
typename std::enable_if<
(IsSomeString<Tgt>::value
|| std::is_same<Tgt, folly::StringPiece>::value)
&& std::is_same<Tgt, Src>::value, Tgt>::type
to(const Src & value) {
return value;
}
/** /**
* to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end * to<SomeString>(v1, v2, ...) uses toAppend() (see below) as back-end
* for all types. * for all types.
...@@ -1403,13 +1409,15 @@ to(const Src & value) { ...@@ -1403,13 +1409,15 @@ to(const Src & value) {
// std::underlying_type became available by gcc 4.7.0 // std::underlying_type became available by gcc 4.7.0
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Src>::value, Tgt>::type typename std::enable_if<
std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
to(const Src & value) { to(const Src & value) {
return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value)); return to<Tgt>(static_cast<typename std::underlying_type<Src>::type>(value));
} }
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type typename std::enable_if<
std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
to(const Src & value) { to(const Src & value) {
return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value)); return static_cast<Tgt>(to<typename std::underlying_type<Tgt>::type>(value));
} }
...@@ -1417,7 +1425,8 @@ to(const Src & value) { ...@@ -1417,7 +1425,8 @@ to(const Src & value) {
#else #else
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Src>::value, Tgt>::type typename std::enable_if<
std::is_enum<Src>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
to(const Src & value) { to(const Src & value) {
/* static */ if (Src(-1) < 0) { /* static */ if (Src(-1) < 0) {
/* static */ if (sizeof(Src) <= sizeof(int)) { /* static */ if (sizeof(Src) <= sizeof(int)) {
...@@ -1435,7 +1444,8 @@ to(const Src & value) { ...@@ -1435,7 +1444,8 @@ to(const Src & value) {
} }
template <class Tgt, class Src> template <class Tgt, class Src>
typename std::enable_if<std::is_enum<Tgt>::value, Tgt>::type typename std::enable_if<
std::is_enum<Tgt>::value && !std::is_same<Src, Tgt>::value, Tgt>::type
to(const Src & value) { to(const Src & value) {
/* static */ if (Tgt(-1) < 0) { /* static */ if (Tgt(-1) < 0) {
/* static */ if (sizeof(Tgt) <= sizeof(int)) { /* static */ if (sizeof(Tgt) <= sizeof(int)) {
......
...@@ -34,6 +34,36 @@ static uint32_t u32; ...@@ -34,6 +34,36 @@ static uint32_t u32;
static int64_t s64; static int64_t s64;
static uint64_t u64; static uint64_t u64;
// Test to<T>(T)
TEST(Conv, Type2Type) {
int intV = 42;
EXPECT_EQ(to<int>(intV), 42);
float floatV = 4.2;
EXPECT_EQ(to<float>(floatV), 4.2f);
double doubleV = 0.42;
EXPECT_EQ(to<double>(doubleV), 0.42);
std::string stringV = "StdString";
EXPECT_EQ(to<std::string>(stringV), "StdString");
folly::fbstring fbStrV = "FBString";
EXPECT_EQ(to<folly::fbstring>(fbStrV), "FBString");
folly::StringPiece spV("StringPiece");
EXPECT_EQ(to<folly::StringPiece>(spV), "StringPiece");
// Rvalues
EXPECT_EQ(to<int>(42), 42);
EXPECT_EQ(to<float>(4.2f), 4.2f);
EXPECT_EQ(to<double>(.42), .42);
EXPECT_EQ(to<std::string>(std::string("Hello")), "Hello");
EXPECT_EQ(to<folly::fbstring>(folly::fbstring("hello")), "hello");
EXPECT_EQ(to<folly::StringPiece>(folly::StringPiece("Forty Two")),
"Forty Two");
}
TEST(Conv, Integral2Integral) { TEST(Conv, Integral2Integral) {
// Same size, different signs // Same size, different signs
s64 = numeric_limits<uint8_t>::max(); s64 = numeric_limits<uint8_t>::max();
......
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