rename fmtlog to async
This commit is contained in:
parent
014dbed507
commit
c94c5595be
@ -4,10 +4,9 @@
|
|||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace fmtlog {
|
namespace fmt {
|
||||||
using namespace fmt;
|
|
||||||
|
|
||||||
template <typename Context> struct basic_format_entry {
|
template <typename Context> struct basic_async_entry {
|
||||||
protected:
|
protected:
|
||||||
using char_type = typename Context::char_type;
|
using char_type = typename Context::char_type;
|
||||||
using format_arg = typename basic_format_args<Context>::format_arg;
|
using format_arg = typename basic_format_args<Context>::format_arg;
|
||||||
@ -17,60 +16,66 @@ protected:
|
|||||||
unsigned long long desc_;
|
unsigned long long desc_;
|
||||||
arg_destructor dtor_;
|
arg_destructor dtor_;
|
||||||
|
|
||||||
FMT_CONSTEXPR basic_format_entry(basic_string_view<char_type> format) : format_(format), desc_(0), dtor_(0) {}
|
FMT_CONSTEXPR basic_async_entry(basic_string_view<char_type> format) : format_(format), desc_(0), dtor_(0) {}
|
||||||
const format_arg* get_format_args() const;
|
const format_arg* get_format_args() const;
|
||||||
|
|
||||||
template <typename OutIt, typename T = OutIt>
|
template <typename OutIt, typename T = OutIt>
|
||||||
using enable_out = std::enable_if_t<fmt::detail::is_output_iterator<OutIt, char_type>::value, T>;
|
using enable_out = std::enable_if_t<detail::is_output_iterator<OutIt, char_type>::value, T>;
|
||||||
public:
|
|
||||||
void destruct() { if (dtor_) dtor_(this); }
|
void destruct() { if (dtor_) dtor_(this); }
|
||||||
|
public:
|
||||||
|
struct dtor_sentry {
|
||||||
|
dtor_sentry(basic_async_entry& entry) : entry_(entry) {}
|
||||||
|
~dtor_sentry() { entry_.destruct(); }
|
||||||
|
basic_async_entry& entry_;
|
||||||
|
};
|
||||||
|
|
||||||
// libfmt public APIs
|
// libfmt public APIs
|
||||||
std::basic_string<char_type> format() const { return fmt::vformat(format_, {desc_, get_format_args()}); }
|
std::basic_string<char_type> format() const { return vformat(format_, {desc_, get_format_args()}); }
|
||||||
|
|
||||||
template <typename OutIt>
|
template <typename OutIt>
|
||||||
auto format_to(OutIt out) const -> enable_out<OutIt> {
|
auto format_to(OutIt out) const -> enable_out<OutIt> {
|
||||||
return fmt::vformat_to(out, format_, {desc_, get_format_args()});
|
return vformat_to(out, format_, {desc_, get_format_args()});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutIt>
|
template <typename OutIt>
|
||||||
auto format_to_n(OutIt out, size_t n) const -> enable_out<OutIt, format_to_n_result<OutIt>> {
|
auto format_to_n(OutIt out, size_t n) const -> enable_out<OutIt, format_to_n_result<OutIt>> {
|
||||||
return fmt::vformat_to(fmt::detail::truncating_iterator<OutIt>(out, n), format_, {desc_, get_format_args()});
|
return vformat_to(detail::truncating_iterator<OutIt>(out, n), format_, {desc_, get_format_args()});
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t formatted_size() const {
|
size_t formatted_size() const {
|
||||||
fmt::detail::counting_buffer<> buf;
|
detail::counting_buffer<> buf;
|
||||||
format_to(buf);
|
format_to(buf);
|
||||||
return buf.count();
|
return buf.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(std::FILE* file = stdout) const { return fmt::vprint(file, format_, {desc_, get_format_args()}); }
|
void print(std::FILE* file = stdout) const { return vprint(file, format_, {desc_, get_format_args()}); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename... Args> struct format_entry : basic_format_entry<Context> {
|
template <typename Context, typename... Args> struct async_entry : basic_async_entry<Context> {
|
||||||
using entry = basic_format_entry<Context>;
|
using entry = basic_async_entry<Context>;
|
||||||
|
|
||||||
format_arg_store<Context, Args...> arg_store_;
|
format_arg_store<Context, Args...> arg_store_;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
FMT_CONSTEXPR format_entry(const S& format_str, const Args&... args) : entry(to_string_view(format_str)), arg_store_(args...) {
|
FMT_CONSTEXPR async_entry(const S& format_str, const Args&... args) : entry(to_string_view(format_str)), arg_store_(args...) {
|
||||||
entry::desc_ = arg_store_.desc;
|
entry::desc_ = arg_store_.desc;
|
||||||
}
|
}
|
||||||
FMT_CONSTEXPR void set_dtor(typename entry::arg_destructor dtor) { this->dtor_ = dtor; }
|
FMT_CONSTEXPR void set_dtor(typename entry::arg_destructor dtor) { this->dtor_ = dtor; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
inline const typename basic_format_entry<Context>::format_arg* basic_format_entry<Context>::get_format_args() const {
|
inline const typename basic_async_entry<Context>::format_arg* basic_async_entry<Context>::get_format_args() const {
|
||||||
union obfuscated_args {
|
union obfuscated_args {
|
||||||
const fmt::detail::value<Context>* values_;
|
const detail::value<Context>* values_;
|
||||||
const format_arg* args_;
|
const format_arg* args_;
|
||||||
intptr_t pointer_; // more efficient to add integer with size, as the compiler is able to avoid emitting branch
|
intptr_t pointer_; // more efficient to add integer with size, as the compiler is able to avoid emitting branch
|
||||||
} args;
|
} args;
|
||||||
auto& entry = static_cast<const format_entry<Context>&>(*this);
|
auto& entry = static_cast<const async_entry<Context>&>(*this);
|
||||||
args.values_ = entry.arg_store_.data_.args_;
|
args.values_ = entry.arg_store_.data_.args_;
|
||||||
if (entry.desc_ & fmt::detail::has_named_args_bit) {
|
if (entry.desc_ & detail::has_named_args_bit) {
|
||||||
args.pointer_ += (desc_ & fmt::detail::is_unpacked_bit) ? sizeof(*args.args_) : sizeof(*args.values_);
|
args.pointer_ += (desc_ & detail::is_unpacked_bit) ? sizeof(*args.args_) : sizeof(*args.values_);
|
||||||
}
|
}
|
||||||
return args.args_;
|
return args.args_;
|
||||||
}
|
}
|
||||||
@ -78,7 +83,7 @@ inline const typename basic_format_entry<Context>::format_arg* basic_format_entr
|
|||||||
//
|
//
|
||||||
// A stored entry looks like:
|
// A stored entry looks like:
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// | basic_format_entry | arg_store | stored_objs... | stored_buffers... |
|
// | basic_async_entry | arg_store | stored_objs... | stored_buffers... |
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -96,9 +101,9 @@ using store_as_object = store_method_constant<store_method::object>;
|
|||||||
using store_as_buffer = store_method_constant<store_method::buffer>;
|
using store_as_buffer = store_method_constant<store_method::buffer>;
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
using stored_as_numeric = std::integral_constant<bool, fmt::detail::is_arithmetic_type(Type::value) || Type::value == fmt::detail::type::pointer_type>;
|
using stored_as_numeric = std::integral_constant<bool, detail::is_arithmetic_type(Type::value) || Type::value == detail::type::pointer_type>;
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
using stored_as_string = std::integral_constant<bool, Type::value == fmt::detail::type::cstring_type || Type::value == fmt::detail::type::string_type>;
|
using stored_as_string = std::integral_constant<bool, Type::value == detail::type::cstring_type || Type::value == detail::type::string_type>;
|
||||||
template <typename T> struct is_basic_string : std::false_type {};
|
template <typename T> struct is_basic_string : std::false_type {};
|
||||||
template <typename C, typename T, typename A> struct is_basic_string<std::basic_string<C, T, A>> : std::true_type {};
|
template <typename C, typename T, typename A> struct is_basic_string<std::basic_string<C, T, A>> : std::true_type {};
|
||||||
template <typename Type, typename T>
|
template <typename Type, typename T>
|
||||||
@ -120,7 +125,7 @@ struct custom_store_method {
|
|||||||
using store_type = std::conditional_t<std::is_same_v<transformed_type, store_as_object>, store_as_object, store_as_buffer>;
|
using store_type = std::conditional_t<std::is_same_v<transformed_type, store_as_object>, store_as_object, store_as_buffer>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Arg, typename Context, typename Type = fmt::detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>>
|
template <typename Arg, typename Context, typename Type = detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>>
|
||||||
struct stored_method_constant : std::integral_constant<store_method, // using class (not template using) to allow easier partial specialization.
|
struct stored_method_constant : std::integral_constant<store_method, // using class (not template using) to allow easier partial specialization.
|
||||||
stored_as_numeric<Type>::value ? store_method::numeric :
|
stored_as_numeric<Type>::value ? store_method::numeric :
|
||||||
stored_as_string<Type>::value ? (stored_as_string_object<Type, Arg>::value ? store_method::object : store_method::buffer) :
|
stored_as_string<Type>::value ? (stored_as_string_object<Type, Arg>::value ? store_method::object : store_method::buffer) :
|
||||||
@ -179,26 +184,26 @@ struct arg_transformer {
|
|||||||
template <typename Context, size_t N> using objoffset_at = std::conditional_t<N == 0, std::integral_constant<size_t, 0>, objsizesum_at<Context, N - 1>>;
|
template <typename Context, size_t N> using objoffset_at = std::conditional_t<N == 0, std::integral_constant<size_t, 0>, objsizesum_at<Context, N - 1>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Arg, typename Context, typename Type = fmt::detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>>
|
template <typename Arg, typename Context, typename Type = detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>>
|
||||||
using transformed_arg_type = std::conditional_t<custom_store_method<Arg, Context>::custom_store, typename custom_store_method<Arg, Context>::transformed_type,
|
using transformed_arg_type = std::conditional_t<custom_store_method<Arg, Context>::custom_store, typename custom_store_method<Arg, Context>::transformed_type,
|
||||||
std::conditional_t<stored_as_string<Type>::value && !stored_as_string_object<Type, Arg>::value, basic_string_view<typename Context::char_type>, std::add_const_t<std::remove_reference_t<Arg>>&>
|
std::conditional_t<stored_as_string<Type>::value && !stored_as_string_object<Type, Arg>::value, basic_string_view<typename Context::char_type>, std::add_const_t<std::remove_reference_t<Arg>>&>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
template <typename Context, typename... Args>
|
template <typename Context, typename... Args>
|
||||||
struct format_entry_constructor {
|
struct async_entry_constructor {
|
||||||
using Entry = format_entry<Context, std::decay_t<transformed_arg_type<Args, Context>>...>;
|
using Entry = async_entry<Context, std::decay_t<transformed_arg_type<Args, Context>>...>;
|
||||||
using Dtor = stored_objs_dtor<Context, sizeof(Entry), Args...>;
|
using Dtor = stored_objs_dtor<Context, sizeof(Entry), Args...>;
|
||||||
using Trans = arg_transformer<Args...>;
|
using Trans = arg_transformer<Args...>;
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
static size_t construct(void* buf, const S& format_str, Args... args) {
|
static size_t construct(void* buf, const S& format_str, Args... args) {
|
||||||
return format_entry_constructor<Context, Args...>(buf, format_str, range(), std::forward<Args>(args)...).get_total_size();
|
return async_entry_constructor<Context, Args...>(buf, format_str, range(), std::forward<Args>(args)...).get_total_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using range = typename range_builder<0, sizeof...(Args)>::type;
|
using range = typename range_builder<0, sizeof...(Args)>::type;
|
||||||
template <typename S, size_t... Indice>
|
template <typename S, size_t... Indice>
|
||||||
constexpr format_entry_constructor(void* buf, const S& format_str, index_list<Indice...>, Args... args) : pEntry(reinterpret_cast<char*>(buf)), pBuffer(get_buffer_store(buf)) {
|
constexpr async_entry_constructor(void* buf, const S& format_str, index_list<Indice...>, Args... args) : pEntry(reinterpret_cast<char*>(buf)), pBuffer(get_buffer_store(buf)) {
|
||||||
auto p = new(buf) Entry(format_str, store<Indice>(std::forward<Args>(args))...);
|
auto p = new(buf) Entry(format_str, store<Indice>(std::forward<Args>(args))...);
|
||||||
p->set_dtor(Dtor::value ? Dtor::destruct : nullptr);
|
p->set_dtor(Dtor::value ? Dtor::destruct : nullptr);
|
||||||
}
|
}
|
||||||
@ -207,16 +212,14 @@ private:
|
|||||||
template <size_t N> transformed_arg_type<arg_at<N>, Context> store(typename Trans::template arg_at<N> arg) {
|
template <size_t N> transformed_arg_type<arg_at<N>, Context> store(typename Trans::template arg_at<N> arg) {
|
||||||
using Arg = typename Trans::template arg_at<N>;
|
using Arg = typename Trans::template arg_at<N>;
|
||||||
using select_store_method = custom_store_method<Arg, Context>;
|
using select_store_method = custom_store_method<Arg, Context>;
|
||||||
using MappedType = fmt::detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>;
|
using MappedType = detail::mapped_type_constant<std::remove_reference_t<Arg>, Context>;
|
||||||
if constexpr (select_store_method::custom_store == true) {
|
if constexpr (select_store_method::custom_store == true) {
|
||||||
using Formatter = typename Context::template formatter_type<std::decay_t<Arg>>;
|
using Formatter = typename Context::template formatter_type<std::decay_t<Arg>>;
|
||||||
|
|
||||||
// fmt::print("store custom arg {} @ {}\n", N, (void*)pBuffer);
|
|
||||||
return Formatter::store(pBuffer, std::forward<Arg>(arg));
|
return Formatter::store(pBuffer, std::forward<Arg>(arg));
|
||||||
}
|
}
|
||||||
else if constexpr (stored_as_string<MappedType>::value && !stored_as_string_object<MappedType, Arg>::value) {
|
else if constexpr (stored_as_string<MappedType>::value && !stored_as_string_object<MappedType, Arg>::value) {
|
||||||
// fmt::print("store string arg {} @ {}({})\n", N, (void*)pBuffer, fmt::detail::arg_mapper<Context>().map(std::forward<Arg>(arg)));
|
return copy_string(pBuffer, detail::arg_mapper<Context>().map(std::forward<Arg>(arg)));
|
||||||
return copy_string(pBuffer, fmt::detail::arg_mapper<Context>().map(std::forward<Arg>(arg)));
|
|
||||||
}
|
}
|
||||||
else if constexpr (stored_as_numeric<MappedType>::value) {
|
else if constexpr (stored_as_numeric<MappedType>::value) {
|
||||||
return std::forward<Arg>(arg);
|
return std::forward<Arg>(arg);
|
||||||
@ -235,14 +238,12 @@ private:
|
|||||||
wchar_t* pStart = reinterpret_cast<wchar_t*>(pBuffer);
|
wchar_t* pStart = reinterpret_cast<wchar_t*>(pBuffer);
|
||||||
wchar_t* pEnd = wcpcpy(pStart, cstr);
|
wchar_t* pEnd = wcpcpy(pStart, cstr);
|
||||||
pBuffer = reinterpret_cast<char*>(pEnd);
|
pBuffer = reinterpret_cast<char*>(pEnd);
|
||||||
// fmt::print("copied wstring ({}) @ {}\n", basic_string_view<wchar_t>(pStart, pEnd - pStart), (void*)pStart);
|
|
||||||
return basic_string_view<wchar_t>(pStart, pEnd - pStart);
|
return basic_string_view<wchar_t>(pStart, pEnd - pStart);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char* pStart = pBuffer;
|
char* pStart = pBuffer;
|
||||||
char* pEnd = stpcpy(pStart, cstr);
|
char* pEnd = stpcpy(pStart, cstr);
|
||||||
pBuffer = pEnd;
|
pBuffer = pEnd;
|
||||||
// fmt::print("copied string ({}) @ {}\n", basic_string_view<char>(pStart, pEnd - pStart), (void*)pStart);
|
|
||||||
return basic_string_view<char>(pStart, pEnd - pStart);
|
return basic_string_view<char>(pStart, pEnd - pStart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,7 +259,6 @@ private:
|
|||||||
char* const pentry = reinterpret_cast<char*>(buf); // entry will be constructed here
|
char* const pentry = reinterpret_cast<char*>(buf); // entry will be constructed here
|
||||||
char* const pobjs = pentry + sizeof(Entry); // objects will be stored starting here
|
char* const pobjs = pentry + sizeof(Entry); // objects will be stored starting here
|
||||||
char* const pbufs = pobjs + get_obj_size(); // buffers will be stored starting here
|
char* const pbufs = pobjs + get_obj_size(); // buffers will be stored starting here
|
||||||
// fmt::print("creating custom arg entry @ {}, {}, {}\n", (void*)pentry, (void*)pobjs, (void*)pbufs);
|
|
||||||
return pbufs;
|
return pbufs;
|
||||||
}
|
}
|
||||||
static constexpr size_t get_obj_size() { return Trans::template objsizesum_at<Context, sizeof...(Args) - 1>::value; }
|
static constexpr size_t get_obj_size() { return Trans::template objsizesum_at<Context, sizeof...(Args) - 1>::value; }
|
||||||
@ -267,48 +267,40 @@ private:
|
|||||||
char* pBuffer;
|
char* pBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context>
|
|
||||||
struct entry_destruct_sentry {
|
|
||||||
using Entry = basic_format_entry<Context>;
|
|
||||||
entry_destruct_sentry(Entry& entry) : entry_(entry) {}
|
|
||||||
~entry_destruct_sentry() { entry_.destruct(); }
|
|
||||||
Entry& entry_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline size_t store_format_entry(void* buf, const S& format_str, Args&&... args) {
|
inline size_t store_async_entry(void* buf, const S& format_str, Args&&... args) {
|
||||||
using Context = buffer_context<Char>;
|
using Context = buffer_context<Char>;
|
||||||
using Constructor = detail::format_entry_constructor<Context, Args&&...>;
|
using Constructor = detail::async_entry_constructor<Context, Args&&...>;
|
||||||
return Constructor::construct(buf, format_str, std::forward<Args>(args)...);
|
return Constructor::construct(buf, format_str, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
inline auto format_entry_to_string(basic_format_entry<Context>& entry) -> decltype(entry.format()) {
|
inline auto async_entry_to_string(basic_async_entry<Context>& entry) -> decltype(entry.format()) {
|
||||||
detail::entry_destruct_sentry<Context> _(entry);
|
typename basic_async_entry<Context>::dtor_sentry _(entry);
|
||||||
return entry.format();
|
return entry.format();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutIt, typename Context>
|
template <typename OutIt, typename Context>
|
||||||
inline auto format_entry_to(OutIt out, basic_format_entry<Context>& entry) -> decltype(entry.format_to(out)) {
|
inline auto async_entry_to(OutIt out, basic_async_entry<Context>& entry) -> decltype(entry.format_to(out)) {
|
||||||
detail::entry_destruct_sentry<Context> _(entry);
|
typename basic_async_entry<Context>::dtor_sentry _(entry);
|
||||||
return entry.format_to(out);
|
return entry.format_to(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename OutIt, typename Context>
|
template <typename OutIt, typename Context>
|
||||||
inline auto format_entry_to_n(OutIt out, size_t n, basic_format_entry<Context>& entry) -> decltype(entry.format_to_n(out, n)) {
|
inline auto async_entry_to_n(OutIt out, size_t n, basic_async_entry<Context>& entry) -> decltype(entry.format_to_n(out, n)) {
|
||||||
detail::entry_destruct_sentry<Context> _(entry);
|
typename basic_async_entry<Context>::dtor_sentry _(entry);
|
||||||
return entry.format_to(out, n);
|
return entry.format_to(out, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Context>
|
template <typename Context>
|
||||||
inline void print_format_entry(std::FILE* f, basic_format_entry<Context>& entry) {
|
inline void print_async_entry(std::FILE* f, basic_async_entry<Context>& entry) {
|
||||||
detail::entry_destruct_sentry<Context> _(entry);
|
typename basic_async_entry<Context>::dtor_sentry _(entry);
|
||||||
entry.print(f);
|
entry.print(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Context> inline void print_format_entry(basic_format_entry<Context>& entry) { print_format_entry<Context>(stdout, entry); }
|
template <typename Context> inline void print_async_entry(basic_async_entry<Context>& entry) { print_async_entry<Context>(stdout, entry); }
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1,10 +1,10 @@
|
|||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
#include "fmtlog.h"
|
#include "async.h"
|
||||||
|
|
||||||
using namespace fmtlog;
|
using namespace fmt;
|
||||||
|
|
||||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||||
inline auto mk_format_entry(const S& format_str, Args&&... args) -> format_entry<buffer_context<Char>, remove_reference_t<Args>...> {
|
inline auto mk_async_entry(const S& format_str, Args&&... args) -> async_entry<buffer_context<Char>, remove_reference_t<Args>...> {
|
||||||
return { format_str, args... };
|
return { format_str, args... };
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,16 +14,16 @@ inline auto mk_format_entry(const S& format_str, Args&&... args) -> format_entry
|
|||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
fmt::print("entry header: {}\n", sizeof(basic_format_entry<format_context>));
|
fmt::print("entry header: {}\n", sizeof(basic_async_entry<format_context>));
|
||||||
auto entry = mk_format_entry("The answer is {}\n", 42);
|
auto entry = mk_async_entry("The answer is {}\n", 42);
|
||||||
print_format_entry(entry);
|
print_async_entry(entry);
|
||||||
|
|
||||||
char buf[2000];
|
char buf[2000];
|
||||||
size_t size = store_format_entry(buf, "This {} is {}{}\n", "answer", std::to_string(4), 2);
|
size_t size = store_async_entry(buf, "This {} is {}{}\n", "answer", std::to_string(4), 2);
|
||||||
fmt::print("entry size: {}\n", size);
|
fmt::print("entry size: {}\n", size);
|
||||||
auto& entryref1 = entry;
|
auto& entryref1 = entry;
|
||||||
auto& entryref = reinterpret_cast<decltype(entryref1)>(buf[0]);
|
auto& entryref = reinterpret_cast<decltype(entryref1)>(buf[0]);
|
||||||
print_format_entry(entryref);
|
print_async_entry(entryref);
|
||||||
|
|
||||||
std::cout << &entryref << "\n" << &(entryref.arg_store_) << "\n" << sizeof(entryref.arg_store_) << std::endl;
|
std::cout << &entryref << "\n" << &(entryref.arg_store_) << "\n" << sizeof(entryref.arg_store_) << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user