Commit 328c9a83 authored by Kenton Varda's avatar Kenton Varda

kj/common.h

parent ed6b71aa
......@@ -31,7 +31,7 @@
#include <vector>
#include <memory>
#include <unordered_map>
#include <kj/macros.h>
#include <kj/common.h>
#include "common.h"
#include "message.h"
......
......@@ -24,7 +24,7 @@
#ifndef CAPNPROTO_BLOB_H_
#define CAPNPROTO_BLOB_H_
#include <kj/macros.h>
#include <kj/common.h>
#include "common.h"
#include <string.h>
......
......@@ -29,6 +29,7 @@
#define CAPNPROTO_COMMON_H_
#include <kj/type-safety.h>
#include <inttypes.h>
namespace capnproto {
......
......@@ -71,7 +71,7 @@ private:
return kj::STR * t;
}
TextBlob&& toContainer(TextBlob&& t) {
return kj::move(t);
return kj::mv(t);
}
TextBlob& toContainer(TextBlob& t) {
return t;
......@@ -91,14 +91,14 @@ struct TextBlob::Branch {
template <typename... Params>
TextBlob::TextBlob(Params&&... params) {
init(toContainer(kj::forward<Params>(params))...);
init(toContainer(kj::fwd<Params>(params))...);
}
TextBlob::TextBlob(kj::Array<TextBlob>&& params) {
branches = kj::newArray<Branch>(params.size());
for (size_t i = 0; i < params.size(); i++) {
branches[i].pos = nullptr;
branches[i].content = kj::move(params[i]);
branches[i].content = kj::mv(params[i]);
}
}
......@@ -119,13 +119,13 @@ void TextBlob::allocate(size_t textSize, size_t branchCount) {
template <typename First, typename... Rest>
void TextBlob::allocate(size_t textSize, size_t branchCount, const First& first, Rest&&... rest) {
allocate(textSize + first.size(), branchCount, kj::forward<Rest>(rest)...);
allocate(textSize + first.size(), branchCount, kj::fwd<Rest>(rest)...);
}
template <typename... Rest>
void TextBlob::allocate(size_t textSize, size_t branchCount,
const TextBlob& first, Rest&&... rest) {
allocate(textSize, branchCount + 1, kj::forward<Rest>(rest)...);
allocate(textSize, branchCount + 1, kj::fwd<Rest>(rest)...);
}
void TextBlob::fill(char* textPos, Branch* branchesPos) {
......@@ -135,27 +135,27 @@ void TextBlob::fill(char* textPos, Branch* branchesPos) {
template <typename First, typename... Rest>
void TextBlob::fill(char* textPos, Branch* branchesPos, First&& first, Rest&&... rest) {
textPos = kj::fill(textPos, kj::forward<First>(first));
fill(textPos, branchesPos, kj::forward<Rest>(rest)...);
textPos = kj::fill(textPos, kj::fwd<First>(first));
fill(textPos, branchesPos, kj::fwd<Rest>(rest)...);
}
template <typename... Rest>
void TextBlob::fill(char* textPos, Branch* branchesPos, TextBlob&& first, Rest&&... rest) {
branchesPos->pos = textPos;
branchesPos->content = kj::move(first);
branchesPos->content = kj::mv(first);
++branchesPos;
fill(textPos, branchesPos, kj::forward<Rest>(rest)...);
fill(textPos, branchesPos, kj::fwd<Rest>(rest)...);
}
template <typename... Params>
void TextBlob::init(Params&&... params) {
allocate(0, 0, params...);
fill(text.begin(), branches.begin(), kj::forward<Params>(params)...);
fill(text.begin(), branches.begin(), kj::fwd<Params>(params)...);
}
template <typename... Params>
TextBlob text(Params&&... params) {
return TextBlob(kj::forward<Params>(params)...);
return TextBlob(kj::fwd<Params>(params)...);
}
template <typename List, typename Func>
......@@ -164,13 +164,13 @@ TextBlob forText(List&& list, Func&& func) {
for (size_t i = 0; i < list.size(); i++) {
items[i] = func(list[i]);
}
return TextBlob(kj::move(items));
return TextBlob(kj::mv(items));
}
template <typename T>
struct ForTextHack {
T list;
ForTextHack(T list): list(kj::forward<T>(list)) {}
ForTextHack(T list): list(kj::fwd<T>(list)) {}
template <typename Func>
TextBlob operator*(Func&& func) {
return forText(list, func);
......@@ -259,14 +259,14 @@ TextBlob nodeName(Schema target, Schema scope) {
auto part = targetParents.back();
auto proto = part.getProto();
if (proto.getScopeId() == 0) {
path = text(kj::move(path), "import \"", proto.getDisplayName(), "\".");
path = text(kj::mv(path), "import \"", proto.getDisplayName(), "\".");
} else {
path = text(kj::move(path), getUnqualifiedName(part), ".");
path = text(kj::mv(path), getUnqualifiedName(part), ".");
}
targetParents.pop_back();
}
return text(kj::move(path), getUnqualifiedName(target));
return text(kj::mv(path), getUnqualifiedName(target));
}
TextBlob genType(schema::Type::Reader type, Schema scope) {
......
......@@ -1396,13 +1396,13 @@ typeName DynamicValue::Builder::AsImpl<typeName>::apply(Builder builder) { \
HANDLE_NUMERIC_TYPE(int8_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int16_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int32_t, checkRoundTrip, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int64_t, kj::implicit_cast, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(int64_t, kj::upcast, unsignedToSigned, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint8_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint16_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint32_t, signedToUnsigned, checkRoundTrip, checkRoundTrip)
HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, kj::implicit_cast, checkRoundTrip)
HANDLE_NUMERIC_TYPE(float, kj::implicit_cast, kj::implicit_cast, kj::implicit_cast)
HANDLE_NUMERIC_TYPE(double, kj::implicit_cast, kj::implicit_cast, kj::implicit_cast)
HANDLE_NUMERIC_TYPE(uint64_t, signedToUnsigned, kj::upcast, checkRoundTrip)
HANDLE_NUMERIC_TYPE(float, kj::upcast, kj::upcast, kj::upcast)
HANDLE_NUMERIC_TYPE(double, kj::upcast, kj::upcast, kj::upcast)
#undef HANDLE_NUMERIC_TYPE
......
......@@ -31,7 +31,7 @@
#ifndef CAPNPROTO_LAYOUT_H_
#define CAPNPROTO_LAYOUT_H_
#include <kj/macros.h>
#include <kj/common.h>
#include "common.h"
#include "blob.h"
......
......@@ -120,7 +120,7 @@ class TemporaryPointer {
// able to return a real pointer to its member.
public:
TemporaryPointer(T&& value): value(kj::move(value)) {}
TemporaryPointer(T&& value): value(kj::mv(value)) {}
TemporaryPointer(const T& value): value(value) {}
inline T* operator->() { return &value; }
......
......@@ -23,7 +23,7 @@
#include <cstddef>
#include <memory>
#include <kj/macros.h>
#include <kj/common.h>
#include "common.h"
#include "layout.h"
......@@ -359,7 +359,7 @@ typename RootType::Reader readMessageUnchecked(const word* data) {
template <typename Reader>
void copyToUnchecked(Reader&& reader, kj::ArrayPtr<word> uncheckedBuffer) {
FlatMessageBuilder builder(uncheckedBuffer);
builder.setRoot(kj::forward<Reader>(reader));
builder.setRoot(kj::fwd<Reader>(reader));
builder.requireFilled();
}
......
......@@ -452,7 +452,7 @@ PackedFdMessageReader::PackedFdMessageReader(
PackedFdMessageReader::PackedFdMessageReader(
kj::AutoCloseFd fd, ReaderOptions options, kj::ArrayPtr<word> scratchSpace)
: FdInputStream(kj::move(fd)),
: FdInputStream(kj::mv(fd)),
BufferedInputStreamWrapper(static_cast<FdInputStream&>(*this)),
PackedMessageReader(static_cast<BufferedInputStreamWrapper&>(*this),
options, scratchSpace) {}
......
......@@ -124,7 +124,7 @@ kj::Array<word> messageToFlatArray(kj::ArrayPtr<const kj::ArrayPtr<const word>>
DCHECK(dst == result.end(), "Buffer overrun/underrun bug in code above.");
return move(result);
return kj::mv(result);
}
// =======================================================================================
......
......@@ -115,7 +115,7 @@ public:
StreamFdMessageReader(kj::AutoCloseFd fd, ReaderOptions options = ReaderOptions(),
kj::ArrayPtr<word> scratchSpace = nullptr)
: FdInputStream(kj::move(fd)), InputStreamMessageReader(*this, options, scratchSpace) {}
: FdInputStream(kj::mv(fd)), InputStreamMessageReader(*this, options, scratchSpace) {}
// Read a message from a file descriptor, taking ownership of the descriptor.
~StreamFdMessageReader();
......
......@@ -21,8 +21,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "macros.h"
#include "common.h"
#include "logging.h"
#include <stdlib.h>
......
......@@ -21,33 +21,47 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef KJ_MACROS_H_
#define KJ_MACROS_H_
// Header that should be #included by everyone.
//
// This defines very simple utilities that are widely applicable.
#include <inttypes.h>
#ifndef KJ_COMMON_H_
#define KJ_COMMON_H_
#ifdef __GNUC__
#ifndef __GXX_EXPERIMENTAL_CXX0X__
#warning "Did you forget to enable C++11? Make sure to pass -std=gnu++11 to GCC."
#if __cplusplus < 201103L
#error "This code requires C++11. Either your compiler does not support it or it is not enabled."
#ifdef __GNUC__
// Compiler claims compatibility with GCC, so presumably supports -std.
#error "Pass -std=c++11 on the compiler command line to enable C++11."
#endif
#endif
#if __clang__
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)
#warning "This library requires at least Clang 3.2."
#endif
#elif __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
#warning "This library requires at least GCC 4.7."
#endif
#ifdef __GNUC__
#if __clang__
#if __clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ < 2)
#warning "This library requires at least Clang 3.2."
#endif
#else
#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
#warning "This library requires at least GCC 4.7."
#endif
#endif
#endif
// =======================================================================================
namespace kj {
typedef unsigned int uint;
typedef unsigned char byte;
// =======================================================================================
// Common macros, especially for common yet compiler-specific features.
#define KJ_DISALLOW_COPY(classname) \
classname(const classname&) = delete; \
classname& operator=(const classname&) = delete
namespace internal {
#define KJ_OFFSETOF(type, member) __builtin_offsetof(type, member)
#define KJ_EXPECT_TRUE(condition) __builtin_expect(condition, true)
......@@ -69,14 +83,20 @@ namespace internal {
#if __clang__
#define KJ_UNUSED_FOR_CLANG __attribute__((unused));
// Clang reports "unused" warnings in some places where GCC does not even allow the "unused"
// attribute.
#else
#define KJ_UNUSED_FOR_CLANG
#endif
namespace internal {
void inlinePreconditionFailure(
const char* file, int line, const char* expectation, const char* macroArgs,
const char* message = nullptr) KJ_NORETURN;
} // namespace internal
#define KJ_INLINE_PRECOND(condition, ...) \
if (KJ_EXPECT_TRUE(condition)); else ::kj::internal::inlinePreconditionFailure( \
__FILE__, __LINE__, #condition, #__VA_ARGS__, ##__VA_ARGS__)
......@@ -91,8 +111,12 @@ void inlinePreconditionFailure(
#define KJ_INLINE_DPRECOND KJ_INLINE_PRECOND
#endif
// #define KJ_STACK_ARRAY(type, name, size, minStack, maxStack)
//
// Allocate an array, preferably on the stack, unless it is too big. On GCC this will use
// variable-sized arrays. For other compilers we could just use a fixed-size array.
// variable-sized arrays. For other compilers we could just use a fixed-size array. `minStack`
// is the stack array size to use if variable-width arrays are not supported. `maxStack` is the
// maximum stack array size if variable-width arrays *are* supported.
#if __clang__
#define KJ_STACK_ARRAY(type, name, size, minStack, maxStack) \
size_t name##_size = (size); \
......@@ -113,13 +137,103 @@ void inlinePreconditionFailure(
kj::arrayPtr(name##_stack, name##_size) : name##_heap
#endif
} // namespace internal
// =======================================================================================
// Template metaprogramming helpers.
template <typename T>
struct NoInfer_ {
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
// the type based on the parameter value. There's something in the standard library for this but
// I didn't want to #include type_traits or whatever.
typedef T Type;
};
template <typename T>
using NoInfer = typename NoInfer_<T>::Type;
template <typename T> struct RemoveReference_ { typedef T Type; };
template <typename T> struct RemoveReference_<T&> { typedef T Type; };
template <typename T> using RemoveReference = typename RemoveReference_<T>::Type;
template <typename> struct IsLvalueReference_ { static constexpr bool value = false; };
template <typename T> struct IsLvalueReference_<T&> { static constexpr bool value = true; };
template <typename T>
inline constexpr bool isLvalueReference() { return IsLvalueReference_<T>::value; }
template <typename T>
T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
// instance<T&&>().
// =======================================================================================
// Equivalents to std::move() and std::forward(), since these are very commonly needed and the
// std header <utility> pulls in lots of other stuff.
//
// We use abbreviated names mv and fwd because these helpers (especially mv) are so commonly used
// that the cost of typing more letters outweighs the cost of being slightly harder to understand
// when first encountered.
template<typename T> constexpr T&& mv(T& t) noexcept { return static_cast<T&&>(t); }
template<typename T>
constexpr T&& fwd(RemoveReference<T>& t) noexcept {
return static_cast<T&&>(t);
}
template<typename T> constexpr T&& fwd(RemoveReference<T>&& t) noexcept {
static_assert(!isLvalueReference<T>(), "Attempting to forward rvalue as lvalue reference.");
return static_cast<T&&>(t);
}
// =======================================================================================
// Upcast/downcast
template <typename To, typename From>
To upcast(From&& from) {
// `upcast<T>(value)` casts `value` to type `T` only if the conversion is implicit. Useful for
// e.g. resolving ambiguous overloads without sacrificing type-safety.
return kj::fwd<From>(from);
}
template <typename To, typename From>
To dynamicDowncastIfAvailable(From* from) {
// If RTTI is disabled, always returns nullptr. Otherwise, works like dynamic_cast. Useful
// in situations where dynamic_cast could allow an optimization, but isn't strictly necessary
// for correctness. It is highly recommended that you try to arrange all your dynamic_casts
// this way, as a dynamic_cast that is necessary for correctness implies a flaw in the interface
// design.
#if KJ_NO_RTTI
return nullptr;
#else
return dynamic_cast<To>(from);
#endif
}
template <typename To, typename From>
To downcast(From* from) {
// Down-cast a value to a sub-type, asserting that the cast is valid. In opt mode this is a
// static_cast, but in debug mode (when RTTI is enabled) a dynamic_cast will be used to verify
// that the value really has the requested type.
// Force a compile error if To is not a subtype of From.
if (false) {
kj::upcast<From*>(To());
}
#if !KJ_NO_RTTI
KJ_INLINE_DPRECOND(
from == nullptr || dynamic_cast<To>(from) != nullptr,
"Value cannot be downcast() to requested type.");
#endif
return static_cast<To>(from);
}
template <typename T, typename U>
T implicit_cast(U u) {
return u;
template <typename To, typename From>
To downcast(From&& from) {
// Reference version of downcast().
return *kj::downcast<To*>(&from);
}
} // namespace kj
#endif // KJ_MACROS_H_
#endif // KJ_COMMON_H_
......@@ -58,7 +58,7 @@ ArrayPtr<const char> operator*(const Stringifier&, Exception::Durability durabil
Exception::Exception(Nature nature, Durability durability, const char* file, int line,
Array<char> description) noexcept
: file(file), line(line), nature(nature), durability(durability),
description(move(description)) {
description(mv(description)) {
traceCount = backtrace(trace, 16);
}
......@@ -82,7 +82,7 @@ Exception::Context::Context(const Context& other) noexcept
}
void Exception::wrapContext(const char* file, int line, Array<char>&& description) {
context = heap<Context>(file, line, move(description), move(context));
context = heap<Context>(file, line, mv(description), mv(context));
}
const char* Exception::what() const noexcept {
......
......@@ -83,7 +83,7 @@ public:
Maybe<Own<Context>> next;
Context(const char* file, int line, Array<char>&& description, Maybe<Own<Context>>&& next)
: file(file), line(line), description(move(description)), next(move(next)) {}
: file(file), line(line), description(mv(description)), next(mv(next)) {}
Context(const Context& other) noexcept;
};
......
......@@ -25,7 +25,7 @@
#define KJ_IO_H_
#include <cstddef>
#include "macros.h"
#include "common.h"
#include "type-safety.h"
namespace kj {
......@@ -243,7 +243,7 @@ class FdInputStream: public InputStream {
public:
explicit FdInputStream(int fd): fd(fd) {};
explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(move(fd)) {}
explicit FdInputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
KJ_DISALLOW_COPY(FdInputStream);
~FdInputStream();
......@@ -259,7 +259,7 @@ class FdOutputStream: public OutputStream {
public:
explicit FdOutputStream(int fd): fd(fd) {};
explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(move(fd)) {}
explicit FdOutputStream(AutoCloseFd fd): fd(fd), autoclose(mv(fd)) {}
KJ_DISALLOW_COPY(FdOutputStream);
~FdOutputStream();
......
......@@ -245,11 +245,11 @@ Log::Context::~Context() {}
void Log::Context::onRecoverableException(Exception&& exception) {
addTo(exception);
next.onRecoverableException(kj::move(exception));
next.onRecoverableException(kj::mv(exception));
}
void Log::Context::onFatalException(Exception&& exception) {
addTo(exception);
next.onFatalException(kj::move(exception));
next.onFatalException(kj::mv(exception));
}
void Log::Context::logMessage(ArrayPtr<const char> text) {
// TODO(someday): We could do something like log the context and then indent all log messages
......
......@@ -28,52 +28,12 @@
#ifndef KJ_TYPE_SAFETY_H_
#define KJ_TYPE_SAFETY_H_
#include "macros.h"
#include "common.h"
#include <cstddef>
#include <string.h>
namespace kj {
typedef unsigned int uint;
typedef unsigned char byte;
template <typename T>
struct NoInfer_ {
// Use NoInfer<T>::Type in place of T for a template function parameter to prevent inference of
// the type based on the parameter value. There's something in the standard library for this but
// I didn't want to #include type_traits or whatever.
typedef T Type;
};
template <typename T>
using NoInfer = typename NoInfer_<T>::Type;
template <typename T> struct RemoveReference_ { typedef T Type; };
template <typename T> struct RemoveReference_<T&> { typedef T Type; };
template <typename> struct IsLvalueReference { static constexpr bool value = false; };
template <typename T> struct IsLvalueReference<T&> { static constexpr bool value = true; };
template <typename T>
using RemoveReference = typename RemoveReference_<T>::Type;
// #including <utility> just for std::move() and std::forward() is excessive. Instead, we
// re-define them here.
template<typename T> constexpr T&& move(T& t) noexcept { return static_cast<T&&>(t); }
template<typename T>
constexpr T&& forward(RemoveReference<T>& t) noexcept {
return static_cast<T&&>(t);
}
template<typename T> constexpr T&& forward(RemoveReference<T>&& t) noexcept {
static_assert(!IsLvalueReference<T>::value, "Attempting to forward rvalue as lvalue reference.");
return static_cast<T&&>(t);
}
template <typename T>
T instance() noexcept;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
// instance<T&&>().
// #including <new> pulls in a lot of crap, but we want placement news. But operator new cannot
// be defined in a namespace, and defining it globally conflicts with the standard library
// definition. So...
......@@ -91,7 +51,7 @@ namespace kj {
template <typename T, typename... Params>
void constructAt(T* location, Params&&... params) {
new (internal::PlacementNew(), location) T(kj::forward<Params>(params)...);
new (internal::PlacementNew(), location) T(kj::fwd<Params>(params)...);
}
// =======================================================================================
......@@ -103,16 +63,16 @@ public:
Maybe(): isSet(false) {}
Maybe(T&& t)
: isSet(true) {
constructAt(&value, kj::move(t));
constructAt(&value, kj::mv(t));
}
Maybe(const T& t)
: isSet(true) {
constructAt(&value, t);
}
Maybe(Maybe&& other) noexcept(noexcept(T(kj::move(other.value))))
Maybe(Maybe&& other) noexcept(noexcept(T(kj::mv(other.value))))
: isSet(other.isSet) {
if (isSet) {
constructAt(&value, kj::move(other.value));
constructAt(&value, kj::mv(other.value));
}
}
Maybe(const Maybe& other)
......@@ -122,10 +82,10 @@ public:
}
}
template <typename U>
Maybe(Maybe<U>&& other) noexcept(noexcept(T(kj::move(other.value))))
Maybe(Maybe<U>&& other) noexcept(noexcept(T(kj::mv(other.value))))
: isSet(other.isSet) {
if (isSet) {
constructAt(&value, kj::move(other.value));
constructAt(&value, kj::mv(other.value));
}
}
template <typename U>
......@@ -156,7 +116,7 @@ public:
value.~T();
}
isSet = true;
constructAt(&value, kj::forward(params)...);
constructAt(&value, kj::fwd(params)...);
}
inline T& operator*() { return value; }
......@@ -171,7 +131,7 @@ public:
}
isSet = other.isSet;
if (isSet) {
constructAt(&value, kj::move(other.value));
constructAt(&value, kj::mv(other.value));
}
}
return *this;
......@@ -232,7 +192,7 @@ public:
// Like map() but allows the function to take an rvalue reference to the value.
if (isSet) {
return func(kj::move(value));
return func(kj::mv(value));
} else {
return nullptr;
}
......@@ -371,7 +331,7 @@ template <typename T>
class HeapValue final: public Disposer {
public:
template <typename... Params>
inline HeapValue(Params&&... params): value(kj::forward<Params>(params)...) {}
inline HeapValue(Params&&... params): value(kj::fwd<Params>(params)...) {}
virtual void dispose(void*) override { delete this; }
......@@ -386,7 +346,7 @@ Own<T> heap(Params&&... params) {
// exact heap implementation is unspecified -- for now it is operator new, but you should not
// assume anything.
auto result = new internal::HeapValue<T>(kj::forward<Params>(params)...);
auto result = new internal::HeapValue<T>(kj::fwd<Params>(params)...);
return Own<T>(&result->value, result);
}
......@@ -562,7 +522,7 @@ public:
template <typename... Params>
void add(Params&&... params) {
KJ_INLINE_DPRECOND(pos < endPtr, "Added too many elements to ArrayBuilder.");
new(&pos->value) T(forward<Params>(params)...);
new(&pos->value) T(kj::fwd<Params>(params)...);
++pos;
}
......
......@@ -415,7 +415,7 @@ inline typename T::Reader {{typeFullName}}::Reader::get{{fieldTitleCase}}(Param&
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::getDynamic(
_reader, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::forward<Param>(param));
_reader, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::fwd<Param>(param));
}
template <typename T, typename Param>
......@@ -425,7 +425,7 @@ inline typename T::Builder {{typeFullName}}::Builder::get{{fieldTitleCase}}(Para
"Must check which() before get()ing a union member.");
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::getDynamic(
_builder, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::forward<Param>(param));
_builder, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::fwd<Param>(param));
}
template <typename T>
......@@ -455,7 +455,7 @@ inline typename T::Builder {{typeFullName}}::Builder::init{{fieldTitleCase}}(Par
{{unionTagOffset}} * ::capnproto::ELEMENTS, {{unionTitleCase}}::{{fieldUpperCase}});
{{/fieldUnion}}
return ::capnproto::internal::PointerHelpers<T>::init(
_builder, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::forward<Params>(params)...);
_builder, {{fieldOffset}} * ::capnproto::POINTERS, ::kj::fwd<Params>(params)...);
}
{{/fieldIsGenericObject}}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment