Commit 515bf2bb authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

A generic tag type

Summary: [Folly] A generic tag type for all your generic tag-related needs. With naming following the pattern of `std::in_place_t` and `std::in_place`.

Reviewed By: kirkshoop

Differential Revision: D13855499

fbshipit-source-id: 50b7e41fbbb843c6c9b766f8b66484d6aa23c167
parent 91bc2fbe
...@@ -134,6 +134,16 @@ ...@@ -134,6 +134,16 @@
namespace folly { namespace folly {
template <typename...>
struct tag_t {};
#if __cplusplus >= 201703L
template <typename... T>
inline constexpr tag_t<T...> tag;
#endif
#if __cpp_lib_bool_constant || _MSC_VER #if __cpp_lib_bool_constant || _MSC_VER
using std::bool_constant; using std::bool_constant;
......
...@@ -1445,14 +1445,15 @@ TEST(Range, LiteralSuffixContainsNulBytes) { ...@@ -1445,14 +1445,15 @@ TEST(Range, LiteralSuffixContainsNulBytes) {
EXPECT_EQ(5u, literalPiece.size()); EXPECT_EQ(5u, literalPiece.size());
} }
class tag {}; namespace {
class fake_tag {};
class fake_string_view { class fake_string_view {
private: private:
StringPiece piece_; StringPiece piece_;
public: public:
using size_type = std::size_t; using size_type = std::size_t;
explicit fake_string_view(char const* s, size_type c, tag = {}) explicit fake_string_view(char const* s, size_type c, fake_tag = {})
: piece_(s, c) {} : piece_(s, c) {}
/* implicit */ operator StringPiece() const { /* implicit */ operator StringPiece() const {
return piece_; return piece_;
...@@ -1461,6 +1462,7 @@ class fake_string_view { ...@@ -1461,6 +1462,7 @@ class fake_string_view {
return rhs == lhs.piece_; return rhs == lhs.piece_;
} }
}; };
} // namespace
TEST(Range, StringPieceExplicitConversionOperator) { TEST(Range, StringPieceExplicitConversionOperator) {
using PieceM = StringPiece; using PieceM = StringPiece;
...@@ -1514,8 +1516,8 @@ TEST(Range, StringPieceExplicitConversionOperator) { ...@@ -1514,8 +1516,8 @@ TEST(Range, StringPieceExplicitConversionOperator) {
EXPECT_EQ("hello", fake_string_view{piecec}); EXPECT_EQ("hello", fake_string_view{piecec});
EXPECT_EQ("hello", piecem.to<fake_string_view>()); EXPECT_EQ("hello", piecem.to<fake_string_view>());
EXPECT_EQ("hello", piecec.to<fake_string_view>()); EXPECT_EQ("hello", piecec.to<fake_string_view>());
EXPECT_EQ("hello", piecem.to<fake_string_view>(tag{})); EXPECT_EQ("hello", piecem.to<fake_string_view>(fake_tag{}));
EXPECT_EQ("hello", piecec.to<fake_string_view>(tag{})); EXPECT_EQ("hello", piecec.to<fake_string_view>(fake_tag{}));
} }
TEST(Range, MutableStringPieceExplicitConversionOperator) { TEST(Range, MutableStringPieceExplicitConversionOperator) {
...@@ -1570,8 +1572,8 @@ TEST(Range, MutableStringPieceExplicitConversionOperator) { ...@@ -1570,8 +1572,8 @@ TEST(Range, MutableStringPieceExplicitConversionOperator) {
EXPECT_EQ("hello", fake_string_view{piecec}); EXPECT_EQ("hello", fake_string_view{piecec});
EXPECT_EQ("hello", piecem.to<fake_string_view>()); EXPECT_EQ("hello", piecem.to<fake_string_view>());
EXPECT_EQ("hello", piecec.to<fake_string_view>()); EXPECT_EQ("hello", piecec.to<fake_string_view>());
EXPECT_EQ("hello", piecem.to<fake_string_view>(tag{})); EXPECT_EQ("hello", piecem.to<fake_string_view>(fake_tag{}));
EXPECT_EQ("hello", piecec.to<fake_string_view>(tag{})); EXPECT_EQ("hello", piecec.to<fake_string_view>(fake_tag{}));
} }
#if FOLLY_HAS_STRING_VIEW #if FOLLY_HAS_STRING_VIEW
......
...@@ -223,6 +223,26 @@ TEST(Traits, actuallyRelocatable) { ...@@ -223,6 +223,26 @@ TEST(Traits, actuallyRelocatable) {
testIsRelocatable<std::vector<char>>(5, 'g'); testIsRelocatable<std::vector<char>>(5, 'g');
} }
struct inspects_tag {
template <typename T>
std::false_type is_char(tag_t<T>) const {
return {};
}
std::true_type is_char(tag_t<char>) const {
return {};
}
};
TEST(Traits, tag) {
inspects_tag f;
EXPECT_FALSE(f.is_char(tag_t<int>{}));
EXPECT_TRUE(f.is_char(tag_t<char>{}));
#if __cplusplus >= 201703L
EXPECT_FALSE(f.is_char(tag<int>));
EXPECT_TRUE(f.is_char(tag<char>));
#endif
}
namespace { namespace {
// has_value_type<T>::value is true if T has a nested type `value_type` // has_value_type<T>::value is true if T has a nested type `value_type`
template <class T, class = void> template <class T, class = void>
......
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