1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*!********************************************************************
Audacity: A Digital Audio Editor
CallableTest.cpp
Paul Licameli
**********************************************************************/
#include <catch2/catch.hpp>
#include "Callable.h"
#include <variant>
// See also VariantTest for more exercise of OverloadSet
using namespace Callable;
namespace {
struct X {
int member{ 0 };
X() = default;
explicit X(int value) : member{ value } {}
explicit X(int value, std::shared_ptr<X>) : member{ value } {}
};
struct TestVisitor {
static int x;
int & operator () (std::monostate) const { return x; }
};
int TestVisitor::x{};
template<auto T> struct TakesNonTypeParameter {};
}
TEST_CASE("Compilation")
{
{
// Test contexpr-ness of OverloadSet constructor, and MemberInvoker too
constexpr auto visitor = OverloadSet{ TestVisitor{}, &X::member },
// and copy constructor
visitor2{ visitor },
// and move constructor
visitor3{ OverloadSet{ TestVisitor{}, &X::member } };
// OverloadSet can be default-constructed, when all the callables can be
constexpr auto visitor4 = OverloadSet<TestVisitor>{};
}
{
// These function objects are of literal types
constexpr auto f1 = UniquePtrFactory<X>::Function;
constexpr auto f2 = UniquePtrFactory<X, int>::Function;
// How to get multiple signatures
constexpr auto f3 = OverloadSet{ f1, f2 };
constexpr auto f4 =
UniquePtrFactory<X, int, std::unique_ptr<X>>::Function;
{
auto p1 = f1();
REQUIRE(p1->member == 0);
auto p2 = f2(1);
REQUIRE(p2->member == 1);
// Demonstrate move of argument
auto p3 = f4(2, move(p2));
REQUIRE(p3->member == 2);
REQUIRE(!p2);
}
{
auto p1 = f3();
REQUIRE(p1->member == 0);
auto p2 = f3(1);
REQUIRE(p2->member == 1);
}
TakesNonTypeParameter<f1> t1{};
TakesNonTypeParameter<f2> t2{};
// Doesn't work with f3 in C++17
}
{
// These function objects are of literal types
constexpr auto f1 = SharedPtrFactory<X>::Function;
constexpr auto f2 = SharedPtrFactory<X, int>::Function;
// How to get multiple signatures
constexpr auto f3 = OverloadSet{ f1, f2 };
constexpr auto f4 =
UniquePtrFactory<X, int, std::shared_ptr<X>>::Function;
{
auto p1 = f1();
REQUIRE(p1->member == 0);
auto p2 = f2(1);
REQUIRE(p2->member == 1);
// Demonstrate move of argument
auto p3 = f4(2, move(p2));
REQUIRE(p3->member == 2);
REQUIRE(!p2);
}
{
auto p1 = f3();
REQUIRE(p1->member == 0);
auto p2 = f3(1);
REQUIRE(p2->member == 1);
}
TakesNonTypeParameter<f1> t1{};
TakesNonTypeParameter<f2> t2{};
// Doesn't work with f3 in C++17
}
{
// These function objects are of literal types
constexpr auto f1 = Constantly<0>::Function;
constexpr auto f2 = Constantly<0, int>::Function;
// How to get multiple signatures
constexpr auto f3 = OverloadSet{ f1, f2 };
REQUIRE(f1() == 0);
REQUIRE(f2(1) == 0);
REQUIRE(f3() == 0);
REQUIRE(f3(1) == 0);
TakesNonTypeParameter<f1> t1{};
TakesNonTypeParameter<f2> t2{};
// Doesn't work with f3 in C++17
}
{
// These function objects are of literal types
constexpr auto f1 = UniqueMaker<X>();
constexpr auto f2 = UniqueMaker<X, int>();
// How to get multiple signatures
constexpr auto f3 = OverloadSet{ f1, f2 };
constexpr auto f4 =
UniqueMaker<X, int, std::shared_ptr<X>>();
{
auto p1 = f1();
REQUIRE(p1->member == 0);
auto p2 = f2(1);
REQUIRE(p2->member == 1);
// Demonstrate move of argument
auto p3 = f4(2, move(p2));
REQUIRE(p3->member == 2);
REQUIRE(!p2);
// Demonstrate how {} can work as an argument
auto p4 = f2({});
// auto p4 = f1({}); sorry
auto p5 = f1(0); // But this works, f1 is still variadic
}
{
auto p1 = f3();
REQUIRE(p1->member == 0);
auto p2 = f3(1);
REQUIRE(p2->member == 1);
}
// generat3ed lambdas won't work as template arguments in C++17
}
}
|