diff --git a/include/tensorwrapper/buffer/eigen.hpp b/include/tensorwrapper/buffer/eigen.hpp index 8fef4a7d..8382c60e 100644 --- a/include/tensorwrapper/buffer/eigen.hpp +++ b/include/tensorwrapper/buffer/eigen.hpp @@ -224,6 +224,9 @@ class Eigen : public Contiguous { /// Implements to_string typename polymorphic_base::string_type to_string_() const override; + /// Implements add_to_stream + std::ostream& add_to_stream_(std::ostream& os) const override; + private: /// True if *this has a PIMPL bool has_pimpl_() const noexcept; diff --git a/include/tensorwrapper/detail_/polymorphic_base.hpp b/include/tensorwrapper/detail_/polymorphic_base.hpp index ccbd094b..b36c8df3 100644 --- a/include/tensorwrapper/detail_/polymorphic_base.hpp +++ b/include/tensorwrapper/detail_/polymorphic_base.hpp @@ -153,6 +153,22 @@ class PolymorphicBase { */ auto to_string() const { return to_string_(); } + /** @brief Adds a string representation of *this to the stream. + * + * This uses `to_string` by default a polymorphic, but allows for better + * optimization of the stream output for specific instances + * + * @note This method is meant primarily for logging/debugging and NOT for + * serialization or archival. + * + * @param[in] os The stream to add *this to. + * + * @return The modified stream with *this added to it. + */ + std::ostream& add_to_stream(std::ostream& os) const { + return add_to_stream_(os); + } + protected: /** @brief No-op default ctor * @@ -227,12 +243,17 @@ class PolymorphicBase { /// Should be overridden by the derived class to provide logging details. virtual string_type to_string_() const { return "{?}"; } + + /// Should be overridden by the derived class to provide logging details + virtual std::ostream& add_to_stream_(std::ostream& os) const { + return os << this->to_string(); + } }; /// Implements printing via ostream for objects deriving from PolymorphicBase template inline std::ostream& operator<<(std::ostream& os, const PolymorphicBase& b) { - return os << b.to_string(); + return b.add_to_stream(os); } } // namespace tensorwrapper::detail_ diff --git a/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp b/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp index ba445ca3..7928ba7f 100644 --- a/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp +++ b/src/tensorwrapper/buffer/detail_/eigen_tensor.hpp @@ -103,6 +103,10 @@ class EigenTensor : public EigenPIMPL { return ss.str(); } + std::ostream& add_to_stream_(std::ostream& os) const override { + return os << m_tensor_; + } + void addition_assignment_(label_type this_labels, label_type lhs_labels, label_type rhs_labels, const_pimpl_reference lhs, const_pimpl_reference rhs) override; diff --git a/src/tensorwrapper/buffer/eigen.cpp b/src/tensorwrapper/buffer/eigen.cpp index 593898fc..a15010ce 100644 --- a/src/tensorwrapper/buffer/eigen.cpp +++ b/src/tensorwrapper/buffer/eigen.cpp @@ -177,6 +177,10 @@ TPARAMS typename EIGEN::polymorphic_base::string_type EIGEN::to_string_() const { return m_pimpl_ ? m_pimpl_->to_string() : ""; } +TPARAMS +std::ostream& EIGEN::add_to_stream_(std::ostream& os) const { + return m_pimpl_ ? m_pimpl_->add_to_stream(os) : os; +} // -- Private methods diff --git a/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp index 8518a6c7..08b5e66a 100644 --- a/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp +++ b/tests/cxx/unit_tests/tensorwrapper/buffer/detail_/eigen_tensor.cpp @@ -15,6 +15,7 @@ */ #include "../../testing/testing.hpp" +#include #include using namespace tensorwrapper; @@ -198,6 +199,16 @@ TEMPLATE_LIST_TEST_CASE("EigenTensor", "", types::floating_point_types) { REQUIRE(vector.to_string() == sone.str() + " " + stwo.str()); } + SECTION("add_to_stream_") { + std::stringstream ss, ss_corr; + ss << std::fixed << std::setprecision(4); + scalar.add_to_stream(ss); + ss_corr << std::fixed << std::setprecision(4); + ss_corr << TestType{1.0}; + REQUIRE(ss.str() == ss_corr.str()); + REQUIRE_FALSE(ss.str() == scalar.to_string()); + } + SECTION("addition_assignment_") { SECTION("scalar") { pimpl_type output;