From 6c5d2a449680f1622ab239f3f425b6f582bf9730 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sat, 23 Dec 2023 22:54:35 -0800 Subject: [PATCH] Start switching to tuples --- .../networktables/NetworkTableInstance.h | 4 +- .../networktables/NetworkTableInstance.inc | 4 +- .../include/networktables/StructTopic.h | 234 +++++++++++------- ntcore/src/test/native/cpp/StructTest.cpp | 56 ++--- wpiutil/src/main/native/include/wpi/DataLog.h | 69 +++--- wpiutil/src/test/native/cpp/DataLogTest.cpp | 41 +-- 6 files changed, 244 insertions(+), 164 deletions(-) diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h index f957ca719ae..c624a2189a9 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.h +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.h @@ -262,11 +262,13 @@ class NetworkTableInstance final { * Gets a raw struct serialized value topic. * * @param name topic name + * @param info optional struct type info * @return Topic */ template requires wpi::StructSerializable - StructTopic GetStructTopic(std::string_view name) const; + StructTopic GetStructTopic(std::string_view name, + const I&... info) const; /** * Gets a raw struct serialized array topic. diff --git a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc b/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc index 490a1ee68a3..28402abb736 100644 --- a/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc +++ b/ntcore/src/main/native/include/networktables/NetworkTableInstance.inc @@ -47,8 +47,8 @@ inline ProtobufTopic NetworkTableInstance::GetProtobufTopic( template requires wpi::StructSerializable inline StructTopic NetworkTableInstance::GetStructTopic( - std::string_view name) const { - return StructTopic{GetTopic(name)}; + std::string_view name, const I&... info) const { + return StructTopic{GetTopic(name), info...}; } template diff --git a/ntcore/src/main/native/include/networktables/StructTopic.h b/ntcore/src/main/native/include/networktables/StructTopic.h index 9f27e01278c..a3d36b673c9 100644 --- a/ntcore/src/main/native/include/networktables/StructTopic.h +++ b/ntcore/src/main/native/include/networktables/StructTopic.h @@ -8,8 +8,10 @@ #include #include +#include #include #include +#include #include #include @@ -41,7 +43,7 @@ class StructSubscriber : public Subscriber { using ParamType = const T&; using TimestampedValueType = Timestamped; - StructSubscriber() = default; + explicit StructSubscriber(const I&... info) : m_info{std::cref(info)...} {} /** * Construct from a subscriber handle; recommended to use @@ -49,19 +51,21 @@ class StructSubscriber : public Subscriber { * * @param handle Native handle * @param defaultValue Default value + * @param info optional struct type info */ - StructSubscriber(NT_Subscriber handle, T defaultValue) - : Subscriber{handle}, m_defaultValue{std::move(defaultValue)} {} + StructSubscriber(NT_Subscriber handle, T defaultValue, const I&... info) + : Subscriber{handle}, + m_defaultValue{std::move(defaultValue)}, + m_info{std::cref(info)...} {} /** * Get the last published value. * If no value has been published or the value cannot be unpacked, returns the * stored default value. * - * @param info optional struct type info * @return value */ - ValueType Get(const I&... info) const { return Get(m_defaultValue, info...); } + ValueType Get() const { return Get(m_defaultValue); } /** * Get the last published value. @@ -69,11 +73,10 @@ class StructSubscriber : public Subscriber { * passed defaultValue. * * @param defaultValue default value to return if no value has been published - * @param info optional struct type info * @return value */ - ValueType Get(const T& defaultValue, const I&... info) const { - return GetAtomic(defaultValue, info...).value; + ValueType Get(const T& defaultValue) const { + return GetAtomic(defaultValue).value; } /** @@ -82,16 +85,19 @@ class StructSubscriber : public Subscriber { * unpacked, does not replace the contents and returns false. * * @param[out] out object to replace contents of - * @param info optional struct type info * @return true if successful */ - bool GetInto(T* out, const I&... info) { + bool GetInto(T* out) { wpi::SmallVector buf; TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {}); - if (view.value.size() < S::GetSize(info...)) { + if (view.value.size() < std::apply(S::GetSize, m_info)) { return false; } else { - wpi::UnpackStructInto(out, view.value, info...); + std::apply( + [&](const I&... info) { + wpi::UnpackStructInto(out, view.value, info...); + }, + m_info); return true; } } @@ -101,12 +107,9 @@ class StructSubscriber : public Subscriber { * If no value has been published or the value cannot be unpacked, returns the * stored default value and a timestamp of 0. * - * @param info optional struct type info * @return timestamped value */ - TimestampedValueType GetAtomic(const I&... info) const { - return GetAtomic(m_defaultValue, info...); - } + TimestampedValueType GetAtomic() const { return GetAtomic(m_defaultValue); } /** * Get the last published value along with its timestamp. @@ -114,17 +117,19 @@ class StructSubscriber : public Subscriber { * passed defaultValue and a timestamp of 0. * * @param defaultValue default value to return if no value has been published - * @param info optional struct type info * @return timestamped value */ - TimestampedValueType GetAtomic(const T& defaultValue, - const I&... info) const { + TimestampedValueType GetAtomic(const T& defaultValue) const { wpi::SmallVector buf; TimestampedRawView view = ::nt::GetAtomicRaw(m_subHandle, buf, {}); - if (view.value.size() < S::GetSize(info...)) { + if (view.value.size() < std::apply(S::GetSize, m_info)) { return {0, 0, defaultValue}; } else { - return {view.time, view.serverTime, S::Unpack(view.value, info...)}; + return { + view.time, view.serverTime, + std::apply( + [&](const I&... info) { return S::Unpack(view.value, info...); }, + m_info)}; } } @@ -136,20 +141,24 @@ class StructSubscriber : public Subscriber { * @note The "poll storage" subscribe option can be used to set the queue * depth. * - * @param info optional struct type info * @return Array of timestamped values; empty array if no valid new changes * have been published since the previous call. */ - std::vector ReadQueue(const I&... info) { + std::vector ReadQueue() { auto raw = ::nt::ReadQueueRaw(m_subHandle); std::vector rv; rv.reserve(raw.size()); for (auto&& r : raw) { - if (r.value.size() < S::GetSize(info...)) { + if (r.value.size() < std::apply(S::GetSize, m_info)) { continue; } else { rv.emplace_back(r.time, r.serverTime, - S::Unpack(std::span(r.value), info...)); + std::apply( + [&](const I&... info) { + return S::Unpack( + std::span(r.value), info...); + }, + m_info)); } } return rv; @@ -161,11 +170,17 @@ class StructSubscriber : public Subscriber { * @return Topic */ TopicType GetTopic() const { - return StructTopic{::nt::GetTopicFromHandle(m_subHandle)}; + return std::apply( + [&](const I&... info) { + return StructTopic{::nt::GetTopicFromHandle(m_subHandle), + info...}; + }, + m_info); } private: ValueType m_defaultValue; + [[no_unique_address]] std::tuple m_info; }; /** @@ -183,19 +198,22 @@ class StructPublisher : public Publisher { using TimestampedValueType = Timestamped; - StructPublisher() = default; + explicit StructPublisher(const I&... info) : m_info{std::cref(info)...} {} StructPublisher(const StructPublisher&) = delete; StructPublisher& operator=(const StructPublisher&) = delete; StructPublisher(StructPublisher&& rhs) - : Publisher{std::move(rhs)}, m_schemaPublished{rhs.m_schemaPublished} {} + : Publisher{std::move(rhs)}, + m_schemaPublished{rhs.m_schemaPublished}, + m_info{rhs.m_info} {} StructPublisher& operator=(StructPublisher&& rhs) { Publisher::operator=(std::move(rhs)); m_schemaPublished.store( rhs.m_schemaPublished.load(std::memory_order_relaxed), std::memory_order_relaxed); + m_info = rhs.m_info; return *this; } @@ -204,31 +222,37 @@ class StructPublisher : public Publisher { * StructTopic::Publish() instead. * * @param handle Native handle + * @param info optional struct type info */ - explicit StructPublisher(NT_Publisher handle) : Publisher{handle} {} + explicit StructPublisher(NT_Publisher handle, const I&... info) + : Publisher{handle}, m_info{std::cref(info)...} {} /** * Publish a new value. * * @param value value to publish - * @param info optional struct type info * @param time timestamp; 0 indicates current NT time should be used */ - void Set(const T& value, const I&... info, int64_t time = 0) { + void Set(const T& value, int64_t time = 0) { if (!m_schemaPublished.exchange(true, std::memory_order_relaxed)) { - GetTopic().GetInstance().template AddStructSchema(info...); + std::apply( + [&](const I&... info) { + GetTopic().GetInstance().template AddStructSchema(info...); + }, + m_info); } - if constexpr (sizeof...(I) == 0 && - wpi::is_constexpr([&] { S::GetSize(info...); })) { - uint8_t buf[S::GetSize(info...)]; - S::Pack(buf, value, info...); - ::nt::SetRaw(m_pubHandle, buf, time); - } else { - wpi::SmallVector buf; - buf.resize_for_overwrite(S::GetSize(info...)); - S::Pack(buf, value, info...); - ::nt::SetRaw(m_pubHandle, buf, time); + if constexpr (sizeof...(I) == 0) { + if constexpr (wpi::is_constexpr([] { S::GetSize(); })) { + uint8_t buf[S::GetSize()]; + S::Pack(buf, value); + ::nt::SetRaw(m_pubHandle, buf, time); + return; + } } + wpi::SmallVector buf; + buf.resize_for_overwrite(std::apply(S::GetSize, m_info)); + std::apply([&](const I&... info) { S::Pack(buf, value, info...); }, m_info); + ::nt::SetRaw(m_pubHandle, buf, time); } /** @@ -237,23 +261,27 @@ class StructPublisher : public Publisher { * published value. * * @param value value - * @param info optional struct type info */ - void SetDefault(const T& value, const I&... info) { + void SetDefault(const T& value) { if (!m_schemaPublished.exchange(true, std::memory_order_relaxed)) { - GetTopic().GetInstance().template AddStructSchema(info...); + std::apply( + [&](const I&... info) { + GetTopic().GetInstance().template AddStructSchema(info...); + }, + m_info); } - if constexpr (sizeof...(I) == 0 && - wpi::is_constexpr([&] { S::GetSize(info...); })) { - uint8_t buf[S::GetSize(info...)]; - S::Pack(buf, value, info...); - ::nt::SetDefaultRaw(m_pubHandle, buf); - } else { - wpi::SmallVector buf; - buf.resize_for_overwrite(S::GetSize(info...)); - S::Pack(buf, value, info...); - ::nt::SetDefaultRaw(m_pubHandle, buf); + if constexpr (sizeof...(I) == 0) { + if constexpr (wpi::is_constexpr([] { S::GetSize(); })) { + uint8_t buf[S::GetSize()]; + S::Pack(buf, value); + ::nt::SetDefaultRaw(m_pubHandle, buf); + return; + } } + wpi::SmallVector buf; + buf.resize_for_overwrite(std::apply(S::GetSize, m_info)); + std::apply([&](const I&... info) { S::Pack(buf, value, info...); }, m_info); + ::nt::SetDefaultRaw(m_pubHandle, buf); } /** @@ -262,11 +290,17 @@ class StructPublisher : public Publisher { * @return Topic */ TopicType GetTopic() const { - return StructTopic{::nt::GetTopicFromHandle(m_pubHandle)}; + return std::apply( + [&](const I&... info) { + return StructTopic{::nt::GetTopicFromHandle(m_pubHandle), + info...}; + }, + m_info); } private: std::atomic_bool m_schemaPublished{false}; + [[no_unique_address]] std::tuple m_info; }; /** @@ -287,7 +321,8 @@ class StructEntry final : public StructSubscriber, using TimestampedValueType = Timestamped; - StructEntry() = default; + explicit StructEntry(const I&... info) + : StructSubscriber{info...}, StructPublisher{info...} {} /** * Construct from an entry handle; recommended to use @@ -295,10 +330,11 @@ class StructEntry final : public StructSubscriber, * * @param handle Native handle * @param defaultValue Default value + * @param info optional struct type info */ - StructEntry(NT_Entry handle, T defaultValue) - : StructSubscriber{handle, std::move(defaultValue)}, - StructPublisher{handle} {} + StructEntry(NT_Entry handle, T defaultValue, const I&... info) + : StructSubscriber{handle, std::move(defaultValue), info...}, + StructPublisher{handle, info...} {} /** * Determines if the native handle is valid. @@ -320,7 +356,7 @@ class StructEntry final : public StructSubscriber, * @return Topic */ TopicType GetTopic() const { - return StructTopic{::nt::GetTopicFromHandle(this->m_subHandle)}; + return this->template Subscriber::GetTopic(); } /** @@ -343,22 +379,26 @@ class StructTopic final : public Topic { using ParamType = const T&; using TimestampedValueType = Timestamped; - StructTopic() = default; + explicit StructTopic(const I&... info) : m_info{std::cref(info)...} {} /** * Construct from a topic handle; recommended to use * NetworkTableInstance::GetStructTopic() instead. * * @param handle Native handle + * @param info optional struct type info */ - explicit StructTopic(NT_Topic handle) : Topic{handle} {} + explicit StructTopic(NT_Topic handle, const I&... info) + : Topic{handle}, m_info{std::cref(info)...} {} /** * Construct from a generic topic. * * @param topic Topic + * @param info optional struct type info */ - explicit StructTopic(Topic topic) : Topic{topic} {} + explicit StructTopic(Topic topic, const I&... info) + : Topic{topic}, m_info{std::cref(info)...} {} /** * Create a new subscriber to the topic. @@ -372,18 +412,21 @@ class StructTopic final : public Topic { * * @param defaultValue default value used when a default is not provided to a * getter function - * @param info optional struct type info * @param options subscribe options * @return subscriber */ [[nodiscard]] SubscriberType Subscribe( - T defaultValue, const I&... info, - const PubSubOptions& options = kDefaultPubSubOptions) { - return StructSubscriber{ - ::nt::Subscribe(m_handle, NT_RAW, - wpi::GetStructTypeString(info...), options), - std::move(defaultValue)}; + T defaultValue, const PubSubOptions& options = kDefaultPubSubOptions) { + return std::apply( + [&](const I&... info) { + return StructSubscriber{ + ::nt::Subscribe(m_handle, NT_RAW, + wpi::GetStructTypeString(info...), + options), + std::move(defaultValue), info...}; + }, + m_info); } /** @@ -398,15 +441,20 @@ class StructTopic final : public Topic { * do not match the topic's data type are dropped (ignored). To determine * if the data type matches, use the appropriate Topic functions. * - * @param info optional struct type info * @param options publish options * @return publisher */ [[nodiscard]] - PublisherType Publish(const I&... info, - const PubSubOptions& options = kDefaultPubSubOptions) { - return StructPublisher{::nt::Publish( - m_handle, NT_RAW, wpi::GetStructTypeString(info...), options)}; + PublisherType Publish(const PubSubOptions& options = kDefaultPubSubOptions) { + return std::apply( + [&](const I&... info) { + return StructPublisher{ + ::nt::Publish(m_handle, NT_RAW, + wpi::GetStructTypeString(info...), + options), + info...}; + }, + m_info); } /** @@ -423,17 +471,22 @@ class StructTopic final : public Topic { * if the data type matches, use the appropriate Topic functions. * * @param properties JSON properties - * @param info optional struct type info * @param options publish options * @return publisher */ [[nodiscard]] PublisherType PublishEx( - const wpi::json& properties, const I&... info, + const wpi::json& properties, const PubSubOptions& options = kDefaultPubSubOptions) { - return StructPublisher{::nt::PublishEx( - m_handle, NT_RAW, wpi::GetStructTypeString(info...), - properties, options)}; + return std::apply( + [&](const I&... info) { + return StructPublisher{ + ::nt::PublishEx(m_handle, NT_RAW, + wpi::GetStructTypeString(info...), + properties, options), + info...}; + }, + m_info); } /** @@ -453,18 +506,25 @@ class StructTopic final : public Topic { * * @param defaultValue default value used when a default is not provided to a * getter function - * @param info optional struct type info * @param options publish and/or subscribe options * @return entry */ [[nodiscard]] - EntryType GetEntry(T defaultValue, const I&... info, + EntryType GetEntry(T defaultValue, const PubSubOptions& options = kDefaultPubSubOptions) { - return StructEntry{ - ::nt::GetEntry(m_handle, NT_RAW, - wpi::GetStructTypeString(info...), options), - std::move(defaultValue)}; + return std::apply( + [&](const I&... info) { + return StructEntry{ + ::nt::GetEntry(m_handle, NT_RAW, + wpi::GetStructTypeString(info...), + options), + std::move(defaultValue), info...}; + }, + m_info); } + + private: + [[no_unique_address]] std::tuple m_info; }; } // namespace nt diff --git a/ntcore/src/test/native/cpp/StructTest.cpp b/ntcore/src/test/native/cpp/StructTest.cpp index 6120d129bff..2312bd1e0de 100644 --- a/ntcore/src/test/native/cpp/StructTest.cpp +++ b/ntcore/src/test/native/cpp/StructTest.cpp @@ -391,20 +391,20 @@ TEST_F(StructTest, StructFixedArrayA) { TEST_F(StructTest, StructB) { Info1 info; nt::StructTopic topic = - inst.GetStructTopic("b"); - nt::StructPublisher pub = topic.Publish(info); - nt::StructPublisher pub2 = topic.PublishEx({{}}, info); - nt::StructSubscriber sub = topic.Subscribe({}, info); - nt::StructEntry entry = topic.GetEntry({}, info); - pub.SetDefault({}, info); - pub.Set({}, info, 5); - sub.Get(info); - sub.Get({}, info); - sub.GetAtomic(info); - sub.GetAtomic({}, info); - entry.SetDefault({}, info); - entry.Set({}, info, 6); - entry.Get({}, info); + inst.GetStructTopic("b", info); + nt::StructPublisher pub = topic.Publish(); + nt::StructPublisher pub2 = topic.PublishEx({{}}); + nt::StructSubscriber sub = topic.Subscribe({}); + nt::StructEntry entry = topic.GetEntry({}); + pub.SetDefault({}); + pub.Set({}, 5); + sub.Get(); + sub.Get({}); + sub.GetAtomic(); + sub.GetAtomic({}); + entry.SetDefault({}); + entry.Set({}, 6); + entry.Get({}); } TEST_F(StructTest, StructArrayB) { @@ -429,24 +429,24 @@ TEST_F(StructTest, StructArrayB) { TEST_F(StructTest, StructFixedArrayB) { Info1 info; nt::StructTopic, Info1> topic = - inst.GetStructTopic, Info1>("b"); - nt::StructPublisher, Info1> pub = topic.Publish(info); + inst.GetStructTopic, Info1>("b", info); + nt::StructPublisher, Info1> pub = topic.Publish(); nt::StructPublisher, Info1> pub2 = - topic.PublishEx({{}}, info); + topic.PublishEx({{}}); nt::StructSubscriber, Info1> sub = - topic.Subscribe({}, info); + topic.Subscribe({}); nt::StructEntry, Info1> entry = - topic.GetEntry({}, info); + topic.GetEntry({}); std::array arr; - pub.SetDefault(arr, info); - pub.Set(arr, info, 5); - sub.Get(info); - sub.Get(arr, info); - sub.GetAtomic(info); - sub.GetAtomic(arr, info); - entry.SetDefault(arr, info); - entry.Set(arr, info, 6); - entry.Get(arr, info); + pub.SetDefault(arr); + pub.Set(arr, 5); + sub.Get(); + sub.Get(arr); + sub.GetAtomic(); + sub.GetAtomic(arr); + entry.SetDefault(arr); + entry.Set(arr, 6); + entry.Get(arr); } } // namespace nt diff --git a/wpiutil/src/main/native/include/wpi/DataLog.h b/wpiutil/src/main/native/include/wpi/DataLog.h index 139b980b9fa..00acb285712 100644 --- a/wpiutil/src/main/native/include/wpi/DataLog.h +++ b/wpiutil/src/main/native/include/wpi/DataLog.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -956,12 +957,13 @@ class StructLogEntry : public DataLogEntry { using S = Struct; public: - StructLogEntry() = default; + explicit StructLogEntry(const I&... info) : m_info{std::cref(info)...} {} StructLogEntry(DataLog& log, std::string_view name, const I&... info, int64_t timestamp = 0) : StructLogEntry{log, name, {}, info..., timestamp} {} StructLogEntry(DataLog& log, std::string_view name, std::string_view metadata, - const I&... info, int64_t timestamp = 0) { + const I&... info, int64_t timestamp = 0) + : m_info{std::cref(info)...} { m_log = &log; log.AddStructSchema(info..., timestamp); m_entry = log.Start(name, S::GetTypeString(info...), metadata, timestamp); @@ -971,22 +973,25 @@ class StructLogEntry : public DataLogEntry { * Appends a record to the log. * * @param data Data to record - * @param info optional struct type info * @param timestamp Time stamp (may be 0 to indicate now) */ - void Append(const T& data, const I&... info, int64_t timestamp = 0) { - if constexpr (sizeof...(I) == 0 && - wpi::is_constexpr([&] { S::GetSize(info...); })) { - uint8_t buf[S::GetSize(info...)]; - S::Pack(buf, data); - m_log->AppendRaw(m_entry, buf, timestamp); - } else { - wpi::SmallVector buf; - buf.resize_for_overwrite(S::GetSize(info...)); - S::Pack(buf, data, info...); - m_log->AppendRaw(m_entry, buf, timestamp); + void Append(const T& data, int64_t timestamp = 0) { + if constexpr (sizeof...(I) == 0) { + if constexpr (wpi::is_constexpr([] { S::GetSize(); })) { + uint8_t buf[S::GetSize()]; + S::Pack(buf, data); + m_log->AppendRaw(m_entry, buf, timestamp); + return; + } } + wpi::SmallVector buf; + buf.resize_for_overwrite(std::apply(S::GetSize, m_info)); + std::apply([&](const I&... info) { S::Pack(buf, data, info...); }, m_info); + m_log->AppendRaw(m_entry, buf, timestamp); } + + private: + [[no_unique_address]] std::tuple m_info; }; /** @@ -998,13 +1003,14 @@ class StructArrayLogEntry : public DataLogEntry { using S = Struct; public: - StructArrayLogEntry() = default; + explicit StructArrayLogEntry(const I&... info) : m_info{std::cref(info)...} {} StructArrayLogEntry(DataLog& log, std::string_view name, const I&... info, int64_t timestamp = 0) : StructArrayLogEntry{log, name, {}, info..., timestamp} {} StructArrayLogEntry(DataLog& log, std::string_view name, std::string_view metadata, const I&... info, - int64_t timestamp = 0) { + int64_t timestamp = 0) + : m_info{std::cref(info)...} { m_log = &log; log.AddStructSchema(info..., timestamp); m_entry = log.Start( @@ -1016,7 +1022,6 @@ class StructArrayLogEntry : public DataLogEntry { * Appends a record to the log. * * @param data Data to record - * @param info optional struct type info * @param timestamp Time stamp (may be 0 to indicate now) */ template @@ -1024,29 +1029,37 @@ class StructArrayLogEntry : public DataLogEntry { requires std::ranges::range && std::convertible_to, T> #endif - void Append(U&& data, const I&... info, int64_t timestamp = 0) { - m_buf.Write( - std::forward(data), - [&](auto bytes) { m_log->AppendRaw(m_entry, bytes, timestamp); }, - info...); + void Append(U&& data, int64_t timestamp = 0) { + std::apply( + [&](const I&... info) { + m_buf.Write( + std::forward(data), + [&](auto bytes) { m_log->AppendRaw(m_entry, bytes, timestamp); }, + info...); + }, + m_info); } /** * Appends a record to the log. * * @param data Data to record - * @param info optional struct type info * @param timestamp Time stamp (may be 0 to indicate now) */ - void Append(std::span data, const I&... info, - int64_t timestamp = 0) { - m_buf.Write( - data, [&](auto bytes) { m_log->AppendRaw(m_entry, bytes, timestamp); }, - info...); + void Append(std::span data, int64_t timestamp = 0) { + std::apply( + [&](const I&... info) { + m_buf.Write( + data, + [&](auto bytes) { m_log->AppendRaw(m_entry, bytes, timestamp); }, + info...); + }, + m_info); } private: StructArrayBuffer m_buf; + [[no_unique_address]] std::tuple m_info; }; /** diff --git a/wpiutil/src/test/native/cpp/DataLogTest.cpp b/wpiutil/src/test/native/cpp/DataLogTest.cpp index 44cb15452be..b4fa20f03a8 100644 --- a/wpiutil/src/test/native/cpp/DataLogTest.cpp +++ b/wpiutil/src/test/native/cpp/DataLogTest.cpp @@ -131,6 +131,7 @@ TEST(DataLogTest, SimpleInt) { TEST(DataLogTest, StructA) { wpi::log::DataLog log{[](auto) {}}; + [[maybe_unused]] wpi::log::StructLogEntry entry0; wpi::log::StructLogEntry entry{log, "a", 5}; entry.Append(ThingA{}); entry.Append(ThingA{}, 7); @@ -138,6 +139,7 @@ TEST(DataLogTest, StructA) { TEST(DataLogTest, StructArrayA) { wpi::log::DataLog log{[](auto) {}}; + [[maybe_unused]] wpi::log::StructArrayLogEntry entry0; wpi::log::StructArrayLogEntry entry{log, "a", 5}; entry.Append({{ThingA{}, ThingA{}}}); entry.Append({{ThingA{}, ThingA{}}}, 7); @@ -145,6 +147,7 @@ TEST(DataLogTest, StructArrayA) { TEST(DataLogTest, StructFixedArrayA) { wpi::log::DataLog log{[](auto) {}}; + [[maybe_unused]] wpi::log::StructArrayLogEntry> entry0; wpi::log::StructLogEntry> entry{log, "a", 5}; std::array arr; entry.Append(arr); @@ -154,17 +157,19 @@ TEST(DataLogTest, StructFixedArrayA) { TEST(DataLogTest, StructB) { wpi::log::DataLog log{[](auto) {}}; Info1 info; + [[maybe_unused]] wpi::log::StructLogEntry entry0{info}; wpi::log::StructLogEntry entry{log, "b", info, 5}; - entry.Append(ThingB{}, info); - entry.Append(ThingB{}, info, 7); + entry.Append(ThingB{}); + entry.Append(ThingB{}, 7); } TEST(DataLogTest, StructArrayB) { wpi::log::DataLog log{[](auto) {}}; Info1 info; + [[maybe_unused]] wpi::log::StructArrayLogEntry entry0{info}; wpi::log::StructArrayLogEntry entry{log, "a", info, 5}; - entry.Append({{ThingB{}, ThingB{}}}, info); - entry.Append({{ThingB{}, ThingB{}}}, info, 7); + entry.Append({{ThingB{}, ThingB{}}}); + entry.Append({{ThingB{}, ThingB{}}}, 7); } TEST(DataLogTest, StructFixedArrayB) { @@ -173,8 +178,8 @@ TEST(DataLogTest, StructFixedArrayB) { wpi::log::StructLogEntry, Info1> entry{log, "a", info, 5}; std::array arr; - entry.Append(arr, info); - entry.Append(arr, info, 7); + entry.Append(arr); + entry.Append(arr, 7); } TEST(DataLogTest, StructC) { @@ -187,14 +192,14 @@ TEST(DataLogTest, StructC) { { Info1 info; wpi::log::StructLogEntry entry{log, "c1", info, 5}; - entry.Append(ThingC{}, info); - entry.Append(ThingC{}, info, 7); + entry.Append(ThingC{}); + entry.Append(ThingC{}, 7); } { Info2 info; wpi::log::StructLogEntry entry{log, "c2", info, 5}; - entry.Append(ThingC{}, info); - entry.Append(ThingC{}, info, 7); + entry.Append(ThingC{}); + entry.Append(ThingC{}, 7); } } @@ -208,14 +213,14 @@ TEST(DataLogTest, StructArrayC) { { Info1 info; wpi::log::StructArrayLogEntry entry{log, "c1", info, 5}; - entry.Append({{ThingC{}, ThingC{}}}, info); - entry.Append({{ThingC{}, ThingC{}}}, info, 7); + entry.Append({{ThingC{}, ThingC{}}}); + entry.Append({{ThingC{}, ThingC{}}}, 7); } { Info2 info; wpi::log::StructArrayLogEntry entry{log, "c2", info, 5}; - entry.Append({{ThingC{}, ThingC{}}}, info); - entry.Append({{ThingC{}, ThingC{}}}, info, 7); + entry.Append({{ThingC{}, ThingC{}}}); + entry.Append({{ThingC{}, ThingC{}}}, 7); } } @@ -231,14 +236,14 @@ TEST(DataLogTest, StructFixedArrayC) { Info1 info; wpi::log::StructLogEntry, Info1> entry{log, "c1", info, 5}; - entry.Append(arr, info); - entry.Append(arr, info, 7); + entry.Append(arr); + entry.Append(arr, 7); } { Info2 info; wpi::log::StructLogEntry, Info2> entry{log, "c2", info, 5}; - entry.Append(arr, info); - entry.Append(arr, info, 7); + entry.Append(arr); + entry.Append(arr, 7); } }