68 lines
2.8 KiB
C++
68 lines
2.8 KiB
C++
// Copyright 2022 gRPC authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|
|
#define GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|
|
|
|
namespace grpc_event_engine {
|
|
namespace experimental {
|
|
namespace internal {
|
|
|
|
// Opt-in trait class for slice conversions.
|
|
// Declare a specialization of this class for any types that are compatible
|
|
// with `SliceCast`. Both ways need to be declared (i.e. if
|
|
// SliceCastable<A,B> exists, you should declare
|
|
// SliceCastable<B,A> too).
|
|
// The type has no members, it's just the existance of the specialization that
|
|
// unlocks SliceCast usage for a type pair.
|
|
template <typename Result, typename T>
|
|
struct SliceCastable;
|
|
|
|
// This is strictly too wide, but consider all types to be SliceCast-able to
|
|
// themselves.
|
|
// Unfortunately this allows `const int& x = SliceCast<int>(x);` which is kind
|
|
// of bogus.
|
|
template <typename A>
|
|
struct SliceCastable<A, A> {};
|
|
|
|
// Cast to `const Result&` from `const T&` without any runtime checks.
|
|
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
|
|
// opted in as compatible via `SliceCastable`.
|
|
template <typename Result, typename T>
|
|
const Result& SliceCast(const T& value, SliceCastable<Result, T> = {}) {
|
|
// Insist upon sizes being equal to catch mismatches.
|
|
// We assume if sizes are opted in and sizes are equal then yes, these two
|
|
// types are expected to be layout compatible and actually appear to be.
|
|
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
|
|
return reinterpret_cast<const Result&>(value);
|
|
}
|
|
|
|
// Cast to `Result&` from `T&` without any runtime checks.
|
|
// This is only valid if `sizeof(Result) == sizeof(T)`, and if `Result`, `T` are
|
|
// opted in as compatible via `SliceCastable`.
|
|
template <typename Result, typename T>
|
|
Result& SliceCast(T& value, SliceCastable<Result, T> = {}) {
|
|
// Insist upon sizes being equal to catch mismatches.
|
|
// We assume if sizes are opted in and sizes are equal then yes, these two
|
|
// types are expected to be layout compatible and actually appear to be.
|
|
static_assert(sizeof(Result) == sizeof(T), "size mismatch");
|
|
return reinterpret_cast<Result&>(value);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace experimental
|
|
} // namespace grpc_event_engine
|
|
|
|
#endif // GRPC_EVENT_ENGINE_INTERNAL_SLICE_CAST_H
|