Just a quick question here guys. I\'ve been searching to no avail so far.
A bit more info here:
stringstream report_string;
report_string << \
How about another approach?
If you make the ostringstream an optional type you can check that its been assigned to before using it.
Imagine a class called lazy<> which lazily constructs an object when needed, then we could do this:
int main()
{
using namespace std;
auto oss1 = lazy();
auto oss2 = lazy();
use(oss1) << "Hello";
if (oss1) cout << use(oss1).str() << endl;
if (oss2) cout << use(oss2).str() << endl;
if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
if_used(oss2,
[](auto& ss) { cout << ss.str() << endl; },
[](auto& oss) { cout << "oss2 is not used" << endl; });
use(oss2) << "Goodbye";
if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });
return 0;
}
yielding this output:
Hello
Hello
oss2 is not used
Goodbye
Advantages:
no redundant construction of the stringstream when not used.
optional provides an exception if the unused stringstream is subsequently used (via const reference)
Full example below with customisable constructor:
I've used std::experimental for the optional, but you could just as easily use boost::optional.
#include
#include
#include
#include
#include
using std::experimental::optional;
namespace detail {
template
struct lazy final
{
template, lazy>::value > * = nullptr>
lazy(Con&& con)
: _constructor(std::forward(con))
{}
T& get() {
if (not bool(_opt)) {
_opt = _constructor();
}
return *_opt;
}
const T& get() const {
return *_opt;
}
bool used() const {
return bool(_opt);
}
operator bool() const {
return used();
}
private:
Constructor _constructor;
optional _opt;
};
template
struct default_construct {
T operator()() const { return T(); }
};
struct no_action {
template
void operator()(T&) const { }
};
}
template >
auto lazy(Constructor&& con = detail::default_construct())
{
return detail::lazy>(std::forward(con));
}
template
auto& use(detail::lazy& l)
{
return l.get();
}
template
auto& use(const detail::lazy& l)
{
return l.get();
}
template
void if_used(detail::lazy& l, F&& f, Else&& e = detail::no_action())
{
if (l.used())
f(l.get());
else
e(l);
}
template
void if_used(const detail::lazy& l, F&& f, Else&& e)
{
if (l.used())
f(l.get());
else
e(l);
}
int main()
{
using namespace std;
auto oss1 = lazy();
auto oss2 = lazy();
use(oss1) << "Hello";
if (oss1) cout << use(oss1).str() << endl;
if (oss2) cout << use(oss2).str() << endl;
if_used(oss1, [](auto& ss) { cout << ss.str() << endl; });
if_used(oss2,
[](auto& ss) { cout << ss.str() << endl; },
[](auto& oss) { cout << "oss2 is not used" << endl; });
use(oss2) << "Goodbye";
if_used(oss2, [](auto& ss) { cout << ss.str() << endl; });
return 0;
}