Commit 968fa24e authored by GILLES Sebastien's avatar GILLES Sebastien

#1470 Use the introduced facility in PrintContainer implementation.

parent 3380f55b
......@@ -91,6 +91,7 @@ BOOST_FIXTURE_TEST_CASE(check_value, TestNS::FixtureNS::Environment)
tuple_iteration::template ExtractValue<InputDataNS::Result::OutputDirectory>(morefem_data.GetInputData().GetTuple(),
result);
std::cout << "VALUE READ = " << result->GetTheValue() << std::endl;
......
......@@ -13,6 +13,7 @@
# include <tuple>
# include <string>
# include <variant>
namespace MoReFEM::Internal::PrintNS
......@@ -25,6 +26,9 @@ namespace MoReFEM::Internal::PrintNS
*
* I recommend [this blog post](https://www.fluentcpp.com/2019/05/07/output-strings-separated-commas-cpp) which was
* a direct inspiration.
*
* \tparam StringT Type of the separator. Usually std::string, but might be char or really anything for which
* operator<< is defined.
*/
template<class StringT = std::string>
class SeparatorFacility
......@@ -40,7 +44,7 @@ namespace MoReFEM::Internal::PrintNS
* \param[in] stream Stream onto which the content is used.
* \param[in] separator Type of separator to be used in the list.
*/
explicit SeparatorFacility(std::ostream& stream, StringT&& separator = ", ");
explicit SeparatorFacility(std::ostream& stream, const StringT& separator = ", ");
//! Destructor.
~SeparatorFacility() = default;
......@@ -57,9 +61,17 @@ namespace MoReFEM::Internal::PrintNS
//! \copydoc doxygen_hide_move_affectation
SeparatorFacility& operator=(self&& rhs) = delete;
template<class T>
friend self& operator<<(self& facility, const T& value);
/*!
* \brief Overload of operator<< for the class.
*
* \param[in,out] facility The facility object; it's on its internal stream that the new content is written.
* \param[in] value Value to print. May be a std::variant, in which case a visitor is called to identify the
* actual type to use for operator<<.
*
* \return \a facility argument (to enable chained calls).
*/
template<class StringU, class T>
friend SeparatorFacility<StringU>& operator<<(SeparatorFacility<StringU>& facility, const T& value);
private:
......@@ -67,13 +79,25 @@ namespace MoReFEM::Internal::PrintNS
std::ostream& stream_;
//! Separator to use between elements of the list.
StringT separator_;
const StringT& separator_;
//! True when we still have to print the first element.
bool is_first_ = true;
};
/*!
* \brief Overload of operator<< for the class.
*
* \param[in,out] facility The facility object; it's on its internal stream that the new content is written.
* \param[in] value Value to print. May be a std::variant, in which case a visitor is called to identify the
* actual type to use for operator<<.
*
* \return \a facility argument (to enable chained calls).
*/
template<class StringT, class T>
SeparatorFacility<StringT>& operator<<(SeparatorFacility<StringT>& facility, const T& value);
/*!
** \brief Facility to print elements of a tuple
......
......@@ -17,7 +17,7 @@ namespace MoReFEM::Internal::PrintNS
template<class StringT>
SeparatorFacility<StringT>::SeparatorFacility(std::ostream& stream, StringT&& separator)
SeparatorFacility<StringT>::SeparatorFacility(std::ostream& stream, const StringT& separator)
: stream_(stream),
separator_(separator)
{ }
......@@ -31,7 +31,23 @@ namespace MoReFEM::Internal::PrintNS
else
facility.stream_ << facility.separator_;
facility.stream_ << value;
if constexpr (Utilities::IsSpecializationOf
<
std::variant,
T
>())
{
auto& stream = facility.stream_;
std::visit([&stream](auto&& arg)
{
stream << arg;
},
value);
}
else
facility.stream_ << value;
return facility;
}
......
......@@ -27,80 +27,10 @@ namespace MoReFEM
{
stream << opener;
auto it = container.cbegin();
auto end = container.cend();
auto size = container.size();
static_cast<void>(end); // avoid compilation warning in release mode
for (decltype(size) i = 0u; i + 1u < size; ++it, ++i)
{
assert(it != end);
// If one of the element is a std::variant, it may be printed... provided the type within the
// variant overloas properly operator<< !
if constexpr (Utilities::IsSpecializationOf
<
std::variant,
typename ContainerT::value_type
>())
{
std::visit([&stream](auto&& arg)
{
using type_arg = std::decay_t<decltype(arg)>;
if constexpr (Utilities::IsSpecializationOf
<
std::map,
type_arg
>())
{
stream << "Map!";
}
else if constexpr (std::is_same_v<type_arg, std::nullptr_t>)
stream << "Nullptr!";
else
stream << arg;
},
*it);
}
else
stream << *it;
stream << separator;
}
Internal::PrintNS::SeparatorFacility separator_facility(stream, separator);
if (size > 0u)
{
// TMP: this is not DRY !!!
if constexpr (Utilities::IsSpecializationOf
<
std::variant,
typename ContainerT::value_type
>())
{
std::visit([&stream](auto&& arg)
{
using type_arg = std::decay_t<decltype(arg)>;
if constexpr (Utilities::IsSpecializationOf
<
std::map,
type_arg
>())
{
stream << "Map!";
}
else if constexpr (std::is_same_v<type_arg, std::nullptr_t>)
stream << "Nullptr!";
else
stream << arg;
},
*it);
}
else
stream << *it;
}
for (const auto& element : container)
separator_facility << element;
stream << closer;
}
......
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