template <class T>
constexpr T StaticConst<T>::value;
-template <class Fun>
-void if_constexpr(std::true_type, Fun fun) {
- fun(Identity{});
+template <class Then>
+decltype(auto) if_constexpr(std::true_type, Then then) {
+ return then(Identity{});
}
-template <class Fun>
-void if_constexpr(std::false_type, Fun) {}
+template <class Then>
+void if_constexpr(std::false_type, Then) {}
+
+template <class Then, class Else>
+decltype(auto) if_constexpr(std::true_type, Then then, Else) {
+ return then(Identity{});
+}
+
+template <class Then, class Else>
+decltype(auto) if_constexpr(std::false_type, Then, Else else_) {
+ return else_(Identity{});
+}
enum class Op : short { eNuke, eMove, eCopy, eType, eAddr, eRefr };
enum class State : short { eEmpty, eInSitu, eOnHeap };
-template <class, class U>
-U&& convert(U&& u) noexcept {
- return static_cast<U&&>(u);
-}
+template <class T>
+struct IsPolyRef : std::false_type {};
-template <class Arg, class I>
-decltype(auto) convert(Poly<I&> u) {
- return poly_cast<Uncvref<Arg>>(u.get());
+template <class T>
+struct IsPolyRef<Poly<T&>> : std::true_type {};
+
+template <class Arg, class U>
+decltype(auto) convert(U&& u) {
+ return detail::if_constexpr(
+ StrictConjunction<
+ IsPolyRef<Uncvref<U>>,
+ Negation<std::is_convertible<U, Arg>>>(),
+ [&](auto id) -> decltype(auto) {
+ return poly_cast<Uncvref<Arg>>(id(u).get());
+ },
+ [&](auto id) -> U&& { return static_cast<U&&>(id(u)); });
}
template <class Fun>
/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5
#pragma message "Folly.Poly requires gcc-5 or greater"
#else
cc = aref + bref;
EXPECT_EQ(6, poly_cast<int>(cc));
}
+
+namespace {
+struct IFrobnicator {
+ template <class Base>
+ struct Interface : Base {
+ void frobnicate(folly::Poly<folly::poly::IRegular&> x) {
+ folly::poly_call<0>(*this, x);
+ }
+ };
+ template <class T>
+ using Members = FOLLY_POLY_MEMBERS(&T::frobnicate);
+};
+using Frobnicator = folly::Poly<IFrobnicator>;
+
+struct my_frobnicator {
+ void frobnicate(folly::Poly<folly::poly::IRegular&>) {
+ // no-op
+ }
+};
+} // namespace
+
+TEST(Poly, PolyRefAsArg) {
+ folly::Poly<folly::poly::IRegular> x = 42;
+ Frobnicator frob = my_frobnicator{};
+ // should not throw:
+ frob.frobnicate(x);
+ // should not throw:
+ frob.frobnicate(folly::Poly<folly::poly::IRegular&>(x));
+}
#endif