Skip to content

Commit

Permalink
Add template helper for indexing ConstantKind by type.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 662978298
  • Loading branch information
jnthntatum authored and copybara-github committed Aug 14, 2024
1 parent fc976d9 commit c4577aa
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 3 deletions.
56 changes: 53 additions & 3 deletions common/constant.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <cstddef>
#include <cstdint>
#include <string>
#include <type_traits>
#include <utility>

#include "absl/base/attributes.h"
Expand Down Expand Up @@ -89,11 +90,60 @@ class StringConstant final : public std::string {
friend class Constant;
};

namespace common_internal {

template <size_t I, typename U, typename T, typename... Ts>
struct ConstantKindIndexer {
static constexpr size_t value =
std::conditional_t<std::is_same_v<U, T>,
std::integral_constant<size_t, I>,
ConstantKindIndexer<I + 1, U, Ts...>>::value;
};

template <size_t I, typename U, typename T>
struct ConstantKindIndexer<I, U, T> {
static constexpr size_t value = std::conditional_t<
std::is_same_v<U, T>, std::integral_constant<size_t, I>,
std::integral_constant<size_t, absl::variant_npos>>::value;
};

template <typename... Ts>
struct ConstantKindImpl {
using VariantType = absl::variant<Ts...>;

template <typename U>
static constexpr size_t IndexOf() {
return ConstantKindIndexer<0, U, Ts...>::value;
}
};

using ConstantKind =
ConstantKindImpl<absl::monostate, std::nullptr_t, bool, int64_t, uint64_t,
double, BytesConstant, StringConstant, absl::Duration,
absl::Time>;

static_assert(ConstantKind::IndexOf<absl::monostate>() == 0);
static_assert(ConstantKind::IndexOf<std::nullptr_t>() == 1);
static_assert(ConstantKind::IndexOf<bool>() == 2);
static_assert(ConstantKind::IndexOf<int64_t>() == 3);
static_assert(ConstantKind::IndexOf<uint64_t>() == 4);
static_assert(ConstantKind::IndexOf<double>() == 5);
static_assert(ConstantKind::IndexOf<BytesConstant>() == 6);
static_assert(ConstantKind::IndexOf<StringConstant>() == 7);
static_assert(ConstantKind::IndexOf<absl::Duration>() == 8);
static_assert(ConstantKind::IndexOf<absl::Time>() == 9);
static_assert(ConstantKind::IndexOf<void>() == absl::variant_npos);

} // namespace common_internal

// Constant is a variant composed of all the literal types support by the Common
// Expression Language.
using ConstantKind = absl::variant<absl::monostate, std::nullptr_t, bool,
int64_t, uint64_t, double, BytesConstant,
StringConstant, absl::Duration, absl::Time>;
using ConstantKind = common_internal::ConstantKind::VariantType;

template <typename U>
constexpr size_t ConstantKindIndexOf() {
return common_internal::ConstantKind::IndexOf<U>();
}

// Returns the `null` literal.
std::string FormatNullConstant();
Expand Down
11 changes: 11 additions & 0 deletions common/constant_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "common/constant.h"

#include <cmath>
#include <cstddef>
#include <cstdint>
#include <string>

#include "absl/strings/has_absl_stringify.h"
Expand All @@ -34,6 +36,7 @@ TEST(Constant, NullValue) {
EXPECT_THAT(const_expr.has_null_value(), IsFalse());
const_expr.set_null_value();
EXPECT_THAT(const_expr.has_null_value(), IsTrue());
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<std::nullptr_t>());
}

TEST(Constant, BoolValue) {
Expand All @@ -43,6 +46,7 @@ TEST(Constant, BoolValue) {
const_expr.set_bool_value(false);
EXPECT_THAT(const_expr.has_bool_value(), IsTrue());
EXPECT_EQ(const_expr.bool_value(), false);
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<bool>());
}

TEST(Constant, IntValue) {
Expand All @@ -52,6 +56,7 @@ TEST(Constant, IntValue) {
const_expr.set_int_value(0);
EXPECT_THAT(const_expr.has_int_value(), IsTrue());
EXPECT_EQ(const_expr.int_value(), 0);
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<int64_t>());
}

TEST(Constant, UintValue) {
Expand All @@ -61,6 +66,7 @@ TEST(Constant, UintValue) {
const_expr.set_uint_value(0);
EXPECT_THAT(const_expr.has_uint_value(), IsTrue());
EXPECT_EQ(const_expr.uint_value(), 0);
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<uint64_t>());
}

TEST(Constant, DoubleValue) {
Expand All @@ -70,6 +76,7 @@ TEST(Constant, DoubleValue) {
const_expr.set_double_value(0);
EXPECT_THAT(const_expr.has_double_value(), IsTrue());
EXPECT_EQ(const_expr.double_value(), 0);
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<double>());
}

TEST(Constant, BytesValue) {
Expand All @@ -79,6 +86,7 @@ TEST(Constant, BytesValue) {
const_expr.set_bytes_value("foo");
EXPECT_THAT(const_expr.has_bytes_value(), IsTrue());
EXPECT_EQ(const_expr.bytes_value(), "foo");
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<BytesConstant>());
}

TEST(Constant, StringValue) {
Expand All @@ -88,6 +96,7 @@ TEST(Constant, StringValue) {
const_expr.set_string_value("foo");
EXPECT_THAT(const_expr.has_string_value(), IsTrue());
EXPECT_EQ(const_expr.string_value(), "foo");
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<StringConstant>());
}

TEST(Constant, DurationValue) {
Expand All @@ -97,6 +106,7 @@ TEST(Constant, DurationValue) {
const_expr.set_duration_value(absl::ZeroDuration());
EXPECT_THAT(const_expr.has_duration_value(), IsTrue());
EXPECT_EQ(const_expr.duration_value(), absl::ZeroDuration());
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<absl::Duration>());
}

TEST(Constant, TimestampValue) {
Expand All @@ -106,6 +116,7 @@ TEST(Constant, TimestampValue) {
const_expr.set_timestamp_value(absl::UnixEpoch());
EXPECT_THAT(const_expr.has_timestamp_value(), IsTrue());
EXPECT_EQ(const_expr.timestamp_value(), absl::UnixEpoch());
EXPECT_EQ(const_expr.kind().index(), ConstantKindIndexOf<absl::Time>());
}

TEST(Constant, Equality) {
Expand Down

0 comments on commit c4577aa

Please # to comment.