2020-03-24 00:12:41 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
#include "mozilla/Assertions.h"
|
|
|
|
#include "mozilla/FunctionRef.h"
|
2020-05-21 01:56:57 +00:00
|
|
|
#include "mozilla/UniquePtr.h"
|
2020-03-24 00:12:41 +00:00
|
|
|
|
2024-02-02 19:21:20 +00:00
|
|
|
using mozilla::FunctionRef;
|
|
|
|
|
2020-03-24 00:12:41 +00:00
|
|
|
#define CHECK(c) \
|
|
|
|
do { \
|
|
|
|
bool cond = !!(c); \
|
|
|
|
MOZ_RELEASE_ASSERT(cond, "Failed assertion: " #c); \
|
|
|
|
} while (false)
|
|
|
|
|
|
|
|
int addConstRefs(const int& arg1, const int& arg2) { return arg1 + arg2; }
|
|
|
|
|
|
|
|
void incrementPointer(int* arg) { (*arg)++; }
|
|
|
|
|
|
|
|
int increment(int arg) { return arg + 1; }
|
|
|
|
|
2020-05-21 01:56:57 +00:00
|
|
|
int incrementUnique(mozilla::UniquePtr<int> ptr) { return *ptr + 1; }
|
|
|
|
|
2020-03-24 00:12:41 +00:00
|
|
|
static bool helloWorldCalled = false;
|
|
|
|
|
|
|
|
void helloWorld() { helloWorldCalled = true; }
|
|
|
|
|
|
|
|
struct S {
|
|
|
|
static int increment(int arg) { return arg + 1; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Incrementor {
|
|
|
|
int operator()(int arg) { return arg + 1; }
|
|
|
|
};
|
|
|
|
|
2024-02-02 19:21:20 +00:00
|
|
|
template <typename Fn>
|
|
|
|
struct Caller;
|
|
|
|
|
|
|
|
template <typename Fn, typename... Params>
|
|
|
|
std::invoke_result_t<Fn, Params...> CallFunctionRef(FunctionRef<Fn> aRef,
|
|
|
|
Params... aParams) {
|
|
|
|
return aRef(std::forward<Params>(aParams)...);
|
|
|
|
}
|
|
|
|
|
2020-03-24 00:12:41 +00:00
|
|
|
static void TestNonmemberFunction() {
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>(increment, 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestStaticMemberFunction() {
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>(&S::increment, 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestFunctionObject() {
|
|
|
|
auto incrementor = Incrementor();
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>(incrementor, 42) == 43);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TestFunctionObjectTemporary() {
|
|
|
|
CHECK(CallFunctionRef<int(int)>(Incrementor(), 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestLambda() {
|
|
|
|
// Test non-capturing lambda
|
|
|
|
auto lambda1 = [](int arg) { return arg + 1; };
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>(lambda1, 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
|
|
|
|
// Test capturing lambda
|
|
|
|
int one = 1;
|
|
|
|
auto lambda2 = [one](int arg) { return arg + one; };
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>(lambda2, 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(int)>([](int arg) { return arg + 1; }, 42) == 43);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestOperatorBool() {
|
2024-02-02 19:21:20 +00:00
|
|
|
auto ToBool = [](FunctionRef<int(int)> aRef) {
|
|
|
|
return static_cast<bool>(aRef);
|
|
|
|
};
|
|
|
|
CHECK(!ToBool({}));
|
|
|
|
CHECK(ToBool(increment));
|
|
|
|
CHECK(!ToBool(nullptr));
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestReferenceParameters() {
|
|
|
|
int x = 1;
|
|
|
|
int y = 2;
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(const int&, const int&)>(addConstRefs, x, y) == 3);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestVoidNoParameters() {
|
|
|
|
CHECK(!helloWorldCalled);
|
2024-02-02 19:21:20 +00:00
|
|
|
CallFunctionRef<void()>(helloWorld);
|
2020-03-24 00:12:41 +00:00
|
|
|
CHECK(helloWorldCalled);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TestPointerParameters() {
|
|
|
|
int x = 1;
|
2024-02-02 19:21:20 +00:00
|
|
|
CallFunctionRef<void(int*)>(incrementPointer, &x);
|
2020-03-24 00:12:41 +00:00
|
|
|
CHECK(x == 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TestImplicitFunctorTypeConversion() {
|
|
|
|
auto incrementor = Incrementor();
|
|
|
|
short x = 1;
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<long(short)>(incrementor, x) == 2);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestImplicitLambdaTypeConversion() {
|
|
|
|
short x = 1;
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<long(short)>([](short arg) { return arg + 1; }, x) ==
|
|
|
|
2);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void TestImplicitFunctionPointerTypeConversion() {
|
|
|
|
short x = 1;
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<long(short)>(&increment, x) == 2);
|
2020-03-24 00:12:41 +00:00
|
|
|
}
|
|
|
|
|
2020-05-21 01:56:57 +00:00
|
|
|
static void TestMoveOnlyArguments() {
|
2024-02-02 19:21:20 +00:00
|
|
|
CHECK(CallFunctionRef<int(mozilla::UniquePtr<int>)>(
|
|
|
|
&incrementUnique, mozilla::MakeUnique<int>(5)) == 6);
|
2020-05-21 01:56:57 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 00:12:41 +00:00
|
|
|
int main() {
|
|
|
|
TestNonmemberFunction();
|
|
|
|
TestStaticMemberFunction();
|
|
|
|
TestFunctionObject();
|
2024-02-02 19:21:20 +00:00
|
|
|
TestFunctionObjectTemporary();
|
2020-03-24 00:12:41 +00:00
|
|
|
TestLambda();
|
|
|
|
TestOperatorBool();
|
|
|
|
TestReferenceParameters();
|
|
|
|
TestPointerParameters();
|
|
|
|
TestVoidNoParameters();
|
|
|
|
TestImplicitFunctorTypeConversion();
|
|
|
|
TestImplicitLambdaTypeConversion();
|
|
|
|
TestImplicitFunctionPointerTypeConversion();
|
2020-05-21 01:56:57 +00:00
|
|
|
TestMoveOnlyArguments();
|
2020-03-24 00:12:41 +00:00
|
|
|
|
|
|
|
printf("TestFunctionRef OK!\n");
|
|
|
|
return 0;
|
|
|
|
}
|