mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-29 11:10:40 +00:00
Seastar recently lost support for the experimental Concepts Technical Specification (TS) and gained support for C++20 concepts. Re-enable concepts in Scylla by updating our use of concepts to the C++20 standard. This change: - peels off uses of the GCC6_CONCEPT macro - removes inclusions of <seastar/gcc6-concepts.hh> - replaces function-style concepts (no longer supported) with equation-style concepts - semicolons added and removed as needed - deprecated std::is_pod replaced by recommended replacement - updates return type constraints to use concepts instead of type names (either std::same_as or std::convertible_to, with std::same_as chosen when possible) No attempt is made to improve the concepts; this is a specification update only. Message-Id: <20200531110254.2555854-1-avi@scylladb.com>
274 lines
11 KiB
C++
274 lines
11 KiB
C++
/*
|
|
* Copyright (C) 2019 ScyllaDB
|
|
*/
|
|
|
|
/*
|
|
* This file is part of Scylla.
|
|
*
|
|
* Scylla is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Scylla is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Scylla. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <seastar/net/inet_address.hh>
|
|
|
|
#include "types.hh"
|
|
#include "types/list.hh"
|
|
#include "types/map.hh"
|
|
#include "types/set.hh"
|
|
#include "types/tuple.hh"
|
|
#include "types/user.hh"
|
|
#include "utils/big_decimal.hh"
|
|
|
|
struct empty_type_impl final : public abstract_type {
|
|
empty_type_impl();
|
|
};
|
|
|
|
struct counter_type_impl final : public abstract_type {
|
|
counter_type_impl();
|
|
};
|
|
|
|
template <typename T>
|
|
struct simple_type_impl : public concrete_type<T> {
|
|
simple_type_impl(abstract_type::kind k, sstring name, std::optional<uint32_t> value_length_if_fixed);
|
|
};
|
|
|
|
template<typename T>
|
|
struct integer_type_impl : public simple_type_impl<T> {
|
|
integer_type_impl(abstract_type::kind k, sstring name, std::optional<uint32_t> value_length_if_fixed);
|
|
};
|
|
|
|
struct byte_type_impl final : public integer_type_impl<int8_t> {
|
|
byte_type_impl();
|
|
};
|
|
|
|
struct short_type_impl final : public integer_type_impl<int16_t> {
|
|
short_type_impl();
|
|
};
|
|
|
|
struct int32_type_impl final : public integer_type_impl<int32_t> {
|
|
int32_type_impl();
|
|
};
|
|
|
|
struct long_type_impl final : public integer_type_impl<int64_t> {
|
|
long_type_impl();
|
|
};
|
|
|
|
struct boolean_type_impl final : public simple_type_impl<bool> {
|
|
boolean_type_impl();
|
|
};
|
|
|
|
template <typename T>
|
|
struct floating_type_impl : public simple_type_impl<T> {
|
|
floating_type_impl(abstract_type::kind k, sstring name, std::optional<uint32_t> value_length_if_fixed);
|
|
};
|
|
|
|
struct double_type_impl final : public floating_type_impl<double> {
|
|
double_type_impl();
|
|
};
|
|
|
|
struct float_type_impl final : public floating_type_impl<float> {
|
|
float_type_impl();
|
|
};
|
|
|
|
struct decimal_type_impl final : public concrete_type<big_decimal> {
|
|
decimal_type_impl();
|
|
};
|
|
|
|
struct duration_type_impl final : public concrete_type<cql_duration> {
|
|
duration_type_impl();
|
|
};
|
|
|
|
struct timestamp_type_impl final : public simple_type_impl<db_clock::time_point> {
|
|
timestamp_type_impl();
|
|
static db_clock::time_point from_sstring(sstring_view s);
|
|
};
|
|
|
|
struct simple_date_type_impl final : public simple_type_impl<uint32_t> {
|
|
simple_date_type_impl();
|
|
static uint32_t from_sstring(sstring_view s);
|
|
};
|
|
|
|
struct time_type_impl final : public simple_type_impl<int64_t> {
|
|
time_type_impl();
|
|
static int64_t from_sstring(sstring_view s);
|
|
};
|
|
|
|
struct string_type_impl : public concrete_type<sstring> {
|
|
string_type_impl(kind k, sstring name);
|
|
};
|
|
|
|
struct ascii_type_impl final : public string_type_impl {
|
|
ascii_type_impl();
|
|
};
|
|
|
|
struct utf8_type_impl final : public string_type_impl {
|
|
utf8_type_impl();
|
|
};
|
|
|
|
struct bytes_type_impl final : public concrete_type<bytes> {
|
|
bytes_type_impl();
|
|
};
|
|
|
|
// This is the old version of timestamp_type_impl, but has been replaced as it
|
|
// wasn't comparing pre-epoch timestamps correctly. This is kept for backward
|
|
// compatibility but shouldn't be used in new code.
|
|
struct date_type_impl final : public concrete_type<db_clock::time_point> {
|
|
date_type_impl();
|
|
};
|
|
|
|
using timestamp_date_base_class = concrete_type<db_clock::time_point>;
|
|
|
|
struct timeuuid_type_impl final : public concrete_type<utils::UUID> {
|
|
timeuuid_type_impl();
|
|
static utils::UUID from_sstring(sstring_view s);
|
|
};
|
|
|
|
struct varint_type_impl final : public concrete_type<utils::multiprecision_int> {
|
|
varint_type_impl();
|
|
};
|
|
|
|
struct inet_addr_type_impl final : public concrete_type<seastar::net::inet_address> {
|
|
inet_addr_type_impl();
|
|
static sstring to_sstring(const seastar::net::inet_address& addr);
|
|
static seastar::net::inet_address from_sstring(sstring_view s);
|
|
};
|
|
|
|
struct uuid_type_impl final : public concrete_type<utils::UUID> {
|
|
uuid_type_impl();
|
|
static utils::UUID from_sstring(sstring_view s);
|
|
};
|
|
|
|
template <typename Func> using visit_ret_type = std::invoke_result_t<Func, const ascii_type_impl&>;
|
|
|
|
template <typename Func> concept CanHandleAllTypes = requires(Func f) {
|
|
{ f(*static_cast<const ascii_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const boolean_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const byte_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const bytes_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const counter_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const date_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const decimal_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const double_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const duration_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const empty_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const float_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const inet_addr_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const int32_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const list_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const long_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const map_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const reversed_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const set_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const short_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const simple_date_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const time_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const timestamp_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const timeuuid_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const tuple_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const user_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const utf8_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const uuid_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
{ f(*static_cast<const varint_type_impl*>(nullptr)) } -> std::same_as<visit_ret_type<Func>>;
|
|
};
|
|
|
|
template<typename Func>
|
|
requires CanHandleAllTypes<Func>
|
|
static inline visit_ret_type<Func> visit(const abstract_type& t, Func&& f) {
|
|
switch (t.get_kind()) {
|
|
case abstract_type::kind::ascii:
|
|
return f(*static_cast<const ascii_type_impl*>(&t));
|
|
case abstract_type::kind::boolean:
|
|
return f(*static_cast<const boolean_type_impl*>(&t));
|
|
case abstract_type::kind::byte:
|
|
return f(*static_cast<const byte_type_impl*>(&t));
|
|
case abstract_type::kind::bytes:
|
|
return f(*static_cast<const bytes_type_impl*>(&t));
|
|
case abstract_type::kind::counter:
|
|
return f(*static_cast<const counter_type_impl*>(&t));
|
|
case abstract_type::kind::date:
|
|
return f(*static_cast<const date_type_impl*>(&t));
|
|
case abstract_type::kind::decimal:
|
|
return f(*static_cast<const decimal_type_impl*>(&t));
|
|
case abstract_type::kind::double_kind:
|
|
return f(*static_cast<const double_type_impl*>(&t));
|
|
case abstract_type::kind::duration:
|
|
return f(*static_cast<const duration_type_impl*>(&t));
|
|
case abstract_type::kind::empty:
|
|
return f(*static_cast<const empty_type_impl*>(&t));
|
|
case abstract_type::kind::float_kind:
|
|
return f(*static_cast<const float_type_impl*>(&t));
|
|
case abstract_type::kind::inet:
|
|
return f(*static_cast<const inet_addr_type_impl*>(&t));
|
|
case abstract_type::kind::int32:
|
|
return f(*static_cast<const int32_type_impl*>(&t));
|
|
case abstract_type::kind::list:
|
|
return f(*static_cast<const list_type_impl*>(&t));
|
|
case abstract_type::kind::long_kind:
|
|
return f(*static_cast<const long_type_impl*>(&t));
|
|
case abstract_type::kind::map:
|
|
return f(*static_cast<const map_type_impl*>(&t));
|
|
case abstract_type::kind::reversed:
|
|
return f(*static_cast<const reversed_type_impl*>(&t));
|
|
case abstract_type::kind::set:
|
|
return f(*static_cast<const set_type_impl*>(&t));
|
|
case abstract_type::kind::short_kind:
|
|
return f(*static_cast<const short_type_impl*>(&t));
|
|
case abstract_type::kind::simple_date:
|
|
return f(*static_cast<const simple_date_type_impl*>(&t));
|
|
case abstract_type::kind::time:
|
|
return f(*static_cast<const time_type_impl*>(&t));
|
|
case abstract_type::kind::timestamp:
|
|
return f(*static_cast<const timestamp_type_impl*>(&t));
|
|
case abstract_type::kind::timeuuid:
|
|
return f(*static_cast<const timeuuid_type_impl*>(&t));
|
|
case abstract_type::kind::tuple:
|
|
return f(*static_cast<const tuple_type_impl*>(&t));
|
|
case abstract_type::kind::user:
|
|
return f(*static_cast<const user_type_impl*>(&t));
|
|
case abstract_type::kind::utf8:
|
|
return f(*static_cast<const utf8_type_impl*>(&t));
|
|
case abstract_type::kind::uuid:
|
|
return f(*static_cast<const uuid_type_impl*>(&t));
|
|
case abstract_type::kind::varint:
|
|
return f(*static_cast<const varint_type_impl*>(&t));
|
|
}
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
template <typename Func> struct data_value_visitor {
|
|
const void* v;
|
|
Func& f;
|
|
auto operator()(const empty_type_impl& t) { return f(t, v); }
|
|
auto operator()(const counter_type_impl& t) { return f(t, v); }
|
|
auto operator()(const reversed_type_impl& t) { return f(t, v); }
|
|
template <typename T> auto operator()(const T& t) {
|
|
return f(t, reinterpret_cast<const typename T::native_type*>(v));
|
|
}
|
|
};
|
|
|
|
// Given an abstract_type and a void pointer to an object of that
|
|
// type, call f with the runtime type of t and v casted to the
|
|
// corresponding native type.
|
|
// This takes an abstract_type and a void pointer instead of a
|
|
// data_value to support reversed_type_impl without requiring that
|
|
// each visitor create a new data_value just to recurse.
|
|
template <typename Func> inline auto visit(const abstract_type& t, const void* v, Func&& f) {
|
|
return ::visit(t, data_value_visitor<Func>{v, f});
|
|
}
|
|
|
|
template <typename Func> inline auto visit(const data_value& v, Func&& f) {
|
|
return ::visit(*v.type(), v._value, f);
|
|
}
|