Skip to content

Commit

Permalink
Export of internal Abseil changes
Browse files Browse the repository at this point in the history
--
b548087c24ae7c2c709e8040a118b5e312d18e2e by Derek Mauro <dmauro@google.com>:

Remove the static initialization of global variables used by absl::Mutex
as requested by Chromium

PiperOrigin-RevId: 317676541

--
f198f5da1e966772efa978ba019bd23576899794 by Greg Miller <jgm@google.com>:

fix: work around gcc-4.8 bug in disjunction

See https://godbolt.org/z/i7-AmM for a repro of the bug.

I realize that Abseil no longer supports gcc 4.8 officially
(https://abseil.io/docs/cpp/platforms/platforms), but Cloud C++ still supports
gcc 4.8 officially, and so it would be nice to get this simple fix in.

fixes #718

PiperOrigin-RevId: 317484459

--
ed233f646530c6c0948213b643cc6919db1bee90 by Chris Kennelly <ckennelly@google.com>:

Avoid determining the size of the duration unit at runtime.

PiperOrigin-RevId: 317376300

--
73d4011c17fcf747a990176924a7adc69d443533 by Greg Falcon <gfalcon@google.com>:

Change spelling of internal detail from `Invoke`/`InvokeT` to `invoke`/`invoke_result_t`.

This matches the spelling of the C++17 standard library names that perform the same operations.

PiperOrigin-RevId: 317311527
GitOrigin-RevId: b548087c24ae7c2c709e8040a118b5e312d18e2e
Change-Id: I131809ff0b92cfdb0d96dc94e94d9c6f751cb0ac
  • Loading branch information
Abseil Team authored and mbxx committed Jun 22, 2020
1 parent 4ccc0fc commit 10cb35e
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 138 deletions.
2 changes: 1 addition & 1 deletion absl/base/call_once.h
Expand Up @@ -175,7 +175,7 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
std::memory_order_relaxed) ||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
scheduling_mode) == kOnceInit) {
base_internal::Invoke(std::forward<Callable>(fn),
base_internal::invoke(std::forward<Callable>(fn),
std::forward<Args>(args)...);
// The call to SpinLockWake below is an optimization, because the waiter
// in SpinLockWait is waiting with a short timeout. The atomic load/store
Expand Down
8 changes: 4 additions & 4 deletions absl/base/internal/invoke.h
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
// absl::base_internal::Invoke(f, args...) is an implementation of
// absl::base_internal::invoke(f, args...) is an implementation of
// INVOKE(f, args...) from section [func.require] of the C++ standard.
//
// [func.require]
Expand All @@ -29,7 +29,7 @@
// is not one of the types described in the previous item;
// 5. f(t1, t2, ..., tN) in all other cases.
//
// The implementation is SFINAE-friendly: substitution failure within Invoke()
// The implementation is SFINAE-friendly: substitution failure within invoke()
// isn't an error.

#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
Expand Down Expand Up @@ -170,13 +170,13 @@ struct Invoker {

// The result type of Invoke<F, Args...>.
template <typename F, typename... Args>
using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
std::declval<F>(), std::declval<Args>()...));

// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
// [func.require] of the C++ standard.
template <typename F, typename... Args>
InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
std::forward<Args>(args)...);
}
Expand Down
136 changes: 71 additions & 65 deletions absl/base/invoke_test.cc
Expand Up @@ -86,130 +86,136 @@ struct FlipFlop {
int member;
};

// CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
// on which one is valid.
template <typename F>
decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
return Invoke(f);
decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
const F& f) {
return base_internal::invoke(f);
}

template <typename F>
decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
return Invoke(f, 42);
decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
const F& f) {
return base_internal::invoke(f, 42);
}

TEST(InvokeTest, Function) {
EXPECT_EQ(1, Invoke(Function, 3, 2));
EXPECT_EQ(1, Invoke(&Function, 3, 2));
EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
}

TEST(InvokeTest, NonCopyableArgument) {
EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
}

TEST(InvokeTest, NonCopyableResult) {
EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
}

TEST(InvokeTest, VoidResult) {
Invoke(NoOp);
}
TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }

TEST(InvokeTest, ConstFunctor) {
EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
}

TEST(InvokeTest, MutableFunctor) {
MutableFunctor f;
EXPECT_EQ(1, Invoke(f, 3, 2));
EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
}

TEST(InvokeTest, EphemeralFunctor) {
EphemeralFunctor f;
EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
}

TEST(InvokeTest, OverloadedFunctor) {
OverloadedFunctor f;
const OverloadedFunctor& cf = f;

EXPECT_EQ("&", Invoke(f));
EXPECT_EQ("& 42", Invoke(f, " 42"));
EXPECT_EQ("&", base_internal::invoke(f));
EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));

EXPECT_EQ("const&", base_internal::invoke(cf));
EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));

EXPECT_EQ("const&", Invoke(cf));
EXPECT_EQ("const& 42", Invoke(cf, " 42"));
EXPECT_EQ("&&", base_internal::invoke(std::move(f)));

EXPECT_EQ("&&", Invoke(std::move(f)));
EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
OverloadedFunctor f2;
EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
}

TEST(InvokeTest, ReferenceWrapper) {
ConstFunctor cf;
MutableFunctor mf;
EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
}

TEST(InvokeTest, MemberFunction) {
std::unique_ptr<Class> p(new Class);
std::unique_ptr<const Class> cp(new Class);
std::unique_ptr<volatile Class> vp(new Class);

EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::Method, *p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::RefMethod, p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::RefMethod, p.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::RefMethod, *p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::RefRefMethod, std::move(*p), 3, 2)); // NOLINT
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, *p, 3, 2));

EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));

EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));

EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *p, 3, 2));
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp, 3, 2));
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp.get(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *vp, 3, 2));

EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
2)); // NOLINT
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));

EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));

EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));

EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));

EXPECT_EQ(1,
base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
3, 2));
EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
make_unique<const Class>(), 3, 2));
}

TEST(InvokeTest, DataMember) {
std::unique_ptr<Class> p(new Class{42});
std::unique_ptr<const Class> cp(new Class{42});
EXPECT_EQ(42, Invoke(&Class::member, p));
EXPECT_EQ(42, Invoke(&Class::member, *p));
EXPECT_EQ(42, Invoke(&Class::member, p.get()));
EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));

Invoke(&Class::member, p) = 42;
Invoke(&Class::member, p.get()) = 42;
base_internal::invoke(&Class::member, p) = 42;
base_internal::invoke(&Class::member, p.get()) = 42;

EXPECT_EQ(42, Invoke(&Class::member, cp));
EXPECT_EQ(42, Invoke(&Class::member, *cp));
EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
}

TEST(InvokeTest, FlipFlop) {
FlipFlop obj = {42};
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
}

TEST(InvokeTest, SfinaeFriendly) {
Expand Down
2 changes: 1 addition & 1 deletion absl/functional/function_ref.h
Expand Up @@ -90,7 +90,7 @@ class FunctionRef<R(Args...)> {
// Used to disable constructors for objects that are not compatible with the
// signature of this FunctionRef.
template <typename F,
typename FR = absl::base_internal::InvokeT<F, Args&&...>>
typename FR = absl::base_internal::invoke_result_t<F, Args&&...>>
using EnableIfCompatible =
typename std::enable_if<std::is_void<R>::value ||
std::is_convertible<FR, R>::value>::type;
Expand Down
16 changes: 8 additions & 8 deletions absl/functional/internal/front_binder.h
Expand Up @@ -33,7 +33,7 @@ namespace functional_internal {
// Invoke the method, expanding the tuple of bound arguments.
template <class R, class Tuple, size_t... Idx, class... Args>
R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {
return base_internal::Invoke(
return base_internal::invoke(
absl::forward<Tuple>(bound).template get<Idx>()...,
absl::forward<Args>(free)...);
}
Expand All @@ -50,22 +50,22 @@ class FrontBinder {
constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)
: bound_args_(absl::forward<Ts>(ts)...) {}

template <class... FreeArgs,
class R = base_internal::InvokeT<F&, BoundArgs&..., FreeArgs&&...>>
template <class... FreeArgs, class R = base_internal::invoke_result_t<
F&, BoundArgs&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) & {
return functional_internal::Apply<R>(bound_args_, Idx(),
absl::forward<FreeArgs>(free_args)...);
}

template <class... FreeArgs,
class R = base_internal::InvokeT<const F&, const BoundArgs&...,
FreeArgs&&...>>
class R = base_internal::invoke_result_t<
const F&, const BoundArgs&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) const& {
return functional_internal::Apply<R>(bound_args_, Idx(),
absl::forward<FreeArgs>(free_args)...);
}

template <class... FreeArgs, class R = base_internal::InvokeT<
template <class... FreeArgs, class R = base_internal::invoke_result_t<
F&&, BoundArgs&&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) && {
// This overload is called when *this is an rvalue. If some of the bound
Expand All @@ -75,8 +75,8 @@ class FrontBinder {
}

template <class... FreeArgs,
class R = base_internal::InvokeT<const F&&, const BoundArgs&&...,
FreeArgs&&...>>
class R = base_internal::invoke_result_t<
const F&&, const BoundArgs&&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) const&& {
// This overload is called when *this is an rvalue. If some of the bound
// arguments are stored by value or rvalue reference, we move them.
Expand Down
4 changes: 2 additions & 2 deletions absl/functional/internal/function_ref.h
Expand Up @@ -71,14 +71,14 @@ template <typename Obj, typename R, typename... Args>
R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
auto o = static_cast<const Obj*>(ptr.obj);
return static_cast<R>(
absl::base_internal::Invoke(*o, std::forward<Args>(args)...));
absl::base_internal::invoke(*o, std::forward<Args>(args)...));
}

template <typename Fun, typename R, typename... Args>
R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
auto f = reinterpret_cast<Fun>(ptr.fun);
return static_cast<R>(
absl::base_internal::Invoke(f, std::forward<Args>(args)...));
absl::base_internal::invoke(f, std::forward<Args>(args)...));
}

template <typename Sig>
Expand Down
10 changes: 2 additions & 8 deletions absl/meta/type_traits.h
Expand Up @@ -219,7 +219,7 @@ using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
// This metafunction is designed to be a drop-in replacement for the C++17
// `std::conjunction` metafunction.
template <typename... Ts>
struct conjunction;
struct conjunction : std::true_type {};

template <typename T, typename... Ts>
struct conjunction<T, Ts...>
Expand All @@ -228,9 +228,6 @@ struct conjunction<T, Ts...>
template <typename T>
struct conjunction<T> : T {};

template <>
struct conjunction<> : std::true_type {};

// disjunction
//
// Performs a compile-time logical OR operation on the passed types (which
Expand All @@ -241,7 +238,7 @@ struct conjunction<> : std::true_type {};
// This metafunction is designed to be a drop-in replacement for the C++17
// `std::disjunction` metafunction.
template <typename... Ts>
struct disjunction;
struct disjunction : std::false_type {};

template <typename T, typename... Ts>
struct disjunction<T, Ts...> :
Expand All @@ -250,9 +247,6 @@ struct disjunction<T, Ts...> :
template <typename T>
struct disjunction<T> : T {};

template <>
struct disjunction<> : std::false_type {};

// negation
//
// Performs a compile-time logical NOT operation on the passed type (which
Expand Down
8 changes: 4 additions & 4 deletions absl/strings/cord.h
Expand Up @@ -857,16 +857,16 @@ ExternalRepReleaserPair NewExternalWithUninitializedReleaser(
struct Rank1 {};
struct Rank0 : Rank1 {};

template <typename Releaser, typename = ::absl::base_internal::InvokeT<
template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
Releaser, absl::string_view>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
::absl::base_internal::Invoke(std::forward<Releaser>(releaser), data);
::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
}

template <typename Releaser,
typename = ::absl::base_internal::InvokeT<Releaser>>
typename = ::absl::base_internal::invoke_result_t<Releaser>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
::absl::base_internal::Invoke(std::forward<Releaser>(releaser));
::absl::base_internal::invoke(std::forward<Releaser>(releaser));
}

// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
Expand Down

0 comments on commit 10cb35e

Please sign in to comment.