I'm looking at making a logging class which has members like Info, Error etc that can configurably output to console, file, or to nowhere.
For efficiency, I would like to avoid the overhead of formatting messages that are going to be thrown away (ie info messages when not running in a verbose mode). If I implement a custom std::streambuf that outputs to nowhere, I imagine that the std::ostream layer will still do all the formatting. Can anyone suggest a way to have a truly "null" std::ostream that avoids doing any work at all on the parameters passed to it with <<?
A swift google came up with this example which may be of use. I offer no guarantees, except that it compiles and runs :-)
#include <streambuf>
#include <ostream>
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
int main() {
onullstream os;
os << 666;
}
all, thanks for sharing the code, I just do a test, then Neil's method will still do the string formating, for example:
#include <streambuf>
#include <ostream>
#include <iostream>
using namespace std;
template <class cT, class traits = std::char_traits<cT> >
class basic_nullbuf: public std::basic_streambuf<cT, traits> {
typename traits::int_type overflow(typename traits::int_type c)
{
return traits::not_eof(c); // indicate success
}
};
template <class cT, class traits = std::char_traits<cT> >
class basic_onullstream: public std::basic_ostream<cT, traits> {
public:
basic_onullstream():
std::basic_ios<cT, traits>(&m_sbuf),
std::basic_ostream<cT, traits>(&m_sbuf)
{
init(&m_sbuf);
}
private:
basic_nullbuf<cT, traits> m_sbuf;
};
typedef basic_onullstream<char> onullstream;
typedef basic_onullstream<wchar_t> wonullstream;
class MyClass
{
int a;
friend ostream& operator<< (ostream&, MyClass const&);
};
ostream& operator<<(ostream& out,MyClass const& b)
{
std::cout<<"call format function!!";
out << b.a;
return out;
}
int main() {
onullstream os;
MyClass obj;
os<<obj;
}
Running this program, you will find that "ostream& operator<<(ostream& out,MyClass const& b)" will be called. So, doing format on the obj will still be called. So, we still can't avoid the overhead of formatting messages.
To prevent the operator<<() invocations from doing formatting, you should know the streamtype at compile-time. This can be done either with macros or with templates.
My template solution follows.
class NullStream {
public:
void setFile() { /* no-op */ }
template<typename TPrintable>
NullStream& operator<<(TPrintable const&)
{ return *this; } /* no-op */
}
template<class TErrorStream> // add TInfoStream etc
class Logger {
public:
TErrorStream& errorStream() {
return m_errorStream;
}
private:
TErrorStream m_errorStream;
};
//usage
int main() {
Logger<std::ofstream> normal_logger; // does real output
normal_logger.errorStream().open("out.txt");
normal_logger.errorStream() << "My age is " << 19;
Logger<NullStream> null_logger; // does zero output with zero overhead
null_logger.errorStream().open("out.txt"); // no-op
null_logger.errorStream() << "My age is " << 19; // no-op
}
Since you have to do this at compile-time, it is of course quite inflexible.
For example, you cannot decide the logging level at runtime from a configuration file.
Probably you'll need more than just text formatting and message filtering. What about multithreading?
I would implement the filtering and multithreading synchronization as the responsibility of a separate class.
However, logging is a not-so-simple problem, and I would try to use existing logging solutions, instead of developing a new one.
Why not using existing logging solutions used by millions of users?
log4j, log4net, log4cxx.., to name just a few..
Related
The relevant code is :
std::fstream fout("Logs.txt");
class Logs;
typedef std::ostream& (*ostream_manipulator2)(std::ostream&);
class LogsOutput
{
public:
LogsOutput() {}
~LogsOutput() {}
Logs * pLogs;
friend LogsOutput& operator<<(LogsOutput &logsClass, std::string &strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, const char *strArg);
friend LogsOutput& operator<<(LogsOutput &logsClass, ostream_manipulator2 pf);
friend LogsOutput& operator<<(LogsOutput &logsClass, uint64_t number);
};
LogsOutput *pLogsOutput;
template <typename T>
T& LOUToutput()
{
if (pLogsOutput)
{
return (*pLogsOutput);
}
else
return fout;
}
I would like to call this function as such :
LOUToutput () << "Print this line " << std::endl;
Sometimes however the LogsOutput class isn't created, therefore dereferencing its pointer would crash in which case i would rather output to file instead.
I understand that the compiler cannot tell at compile time whether the LogsOutput class will be instantiated or not and thus cannot deduce the type of the template, but I don't see any other way I could make it work.
So my question is how can my function return a different type based on a run time condition ?
The complex solution to this is to use inheritance. If you were to inherit from std::ostream, you could return a common base class (Here is a discussion if you are interested: How to inherit from std::ostream?)
The simpler solution, imo., is to return a proxy class that redirects output as necessary.
struct LogProxy {
LogsOutput *pLog;
// ...
LogProxy &operator<<(std::string &o) {
if(pLogsOutput) {
*pLog << o;
} else {
// Assuming this is available as a global.. You probably don't want to do that
fout << o;
}
return *this;
}
// ....
};
LogProxy LOUToutput() {
return LogProxy { pLogsOutput; };
}
A few other general comments:
If you want to use templates you would need to make this a compile time condition. You could use something like std::enable_if<> to provide multiple template overloads of LOUToutput() which choose at compile time where to log to.
I'm guessing it was just for the purposes of posting to SO, but your code has multiple globals declared in a header file. You'll need to fix that.
There are no const declarations on your code. A lot of those operators look like they should at least be declared const on their output (string,.etc.) parameters.
EDIT: Here is a working (compiles correctly) sample of this idea:
#include <iostream>
struct PRXY {
bool cond;
const PRXY &operator<<(const std::string &t) const {
if(cond) {
std::cout << t;
} else {
std::cerr << t;
}
return *this;
}
};
PRXY pr(bool cond) {
return PRXY { cond };
}
void test() {
pr(false) << "Hello";
}
Let's suppose originally I have the following design using CRTP:
template<class Outputter> class Generator {
protected:
vector<int> v;
private:
void work(ostream& out) {
// perform first part of some complex operations on v
out << *static_cast<Outputter *>(this);
// perform second part of some complex operations on v
out << *static_cast<Outputter *>(this);
// many more ....
// perform some final actions
}
public:
Generator(unsigned length): v(length) {}
friend ostream& operator<<(ostream& out, Outputter&& generator) {
// perform some preparation work
work(out);
// perform some final actions
return out;
}
};
class SimpleDumpOutputter : public Generator<SimpleDumpOutputter> {
private:
unsigned count;
public:
SimpleDumpOutputter(unsigned length): Generator(length), count() {}
friend ostream& operator<<(ostream& out, SimpleDumpOutputter& outputter) {
out << "Step " << ++count << " of calculation: "
copy(outputter.v.begin(), outputter.v.end(), ostream_iterator<int>(out, " "));
out << endl;
return out;
}
};
class FancyOutputter : public Generator<FancyOutputter> { // create a graph using graphviz's dot language to visualise v
private:
// abbreviated
public:
FancyOutputter(unsigned length): Generator(length) {}
friend ostream& operator<<(ostream& out, FancyOutputter& outputter) {
// write statements to out
return out;
}
};
// some more different Outputters, for example an Outputter that creates a pretty LaTeX document
In this design, there is a Generator CRTP class template that performs complex calculations on the vector<int> v and prints the result at each step/part of calculation using its derived classes's befriended operator<<.
Here's an interesting concept that I want to implement: I would want outputs in multiple formats in a single execution. Specifically, I thought I could do:
template<class Outputters> class AggregateOutputter : public Generator<AggregateOutputter<Outputters...> > {
private:
static const unsigned outputter_count = sizeof...(Outputters);
typedef array<ostream *, outputter_count> DestArr;
DestArr destinations;
public:
AggregateOutputter(unsigned v_length, DestArr destinations): IsomerGenerator<AggregateOutputter<Outputters...> >(length), destinations(destinations) {}
friend ostream& operator<<(ostream&, AggregateOutputter& outputter); // first argument is dummy, because we would use the ostreams in destinations
}
The idea is that the user would use, say, AggregateOutputter<SimpleDumpOutputter, FancyOutputter and construct the object with an array of two ostreams. Whenever Generator calls operator<< on the outputter class, the AggregateOutputter will iterate through the ostreams in destinations and the types in Outputters and invoke something along the lines of *dest_iter << *static_cast<Outputter_Iter>(this);.
I'm not sure how this would work though. I'm not sure whether multiple inheritance can be used this way, whether it is possible to "zip" between an array and a pack of parameterised types. Is anyone knowledgable in this situation?
I modified your original design. I thought Generator doing a bunch of calculations when the output operator is called is surprising to say the least. Also for your AggregateOutputter to output to ignore the ostream parameter of << is also surprising. Also, Outputter does not have an is-a relationship with Generator.
I tried to separate out the concerns, and ended up not using CRTP but using variadic templates, but I think it does what you want.
http://ideone.com/xQrnW4
#include <vector>
#include <iostream>
#include <iterator>
#include <array>
using namespace std;
class Generator {
protected:
vector<int> v;
public:
Generator(unsigned length): v(length) {}
template<class Outputter>
void do_calculations_with_output(Outputter& out){
// perform first part of some complex operations on v
out.output(v);
// perform second part of some complex operations on v
out.output(v);
// perform some final actions
}
};
class SimpleDumpOutputter {
private:
ostream* out;
unsigned count;
public:
SimpleDumpOutputter(ostream& os): out(&os), count() {}
template<class C>
void output(const C& c) {
*out << "Step " << ++count << " of calculation: ";
copy(c.begin(),c.end(), ostream_iterator<int>(*out, " "));
*out << endl;
}
};
class FancyOutputter {
ostream* out;
int count;
public:
FancyOutputter(ostream& os): out(&os),count() {}
template<class C>
void output(const C& c) {
// create a graph using graphviz's dot language to ease visualisation of v
*out << "Step " << ++count << " of calculation: ";
*out << "Graphviz output\n";
}
};
template<class... Outputters> class AggregateOutputter : private Outputters... {
private:
template<class First, class... Rest>
struct output_helper{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
output_helper<Rest...>::do_output(pthis,c);
}
};
template<class First>
struct output_helper<First>{
template<class C>
static void do_output(AggregateOutputter* pthis,const C& c){
static_cast<First*>(pthis)->output(c);
}
};
public:
template<class... Out>
AggregateOutputter( Out&... out): Outputters(out)...{}
template<class C>
void output(const C& c) {
output_helper<Outputters...>::do_output(this,c);
}
};
int main(){
AggregateOutputter<FancyOutputter,SimpleDumpOutputter> out(cout,cout);
Generator g(10);
g.do_calculations_with_output(out);
}
Okay, here's a solution I came up with, after being inspired by John Bandela's solution here. (see my comment on the answer for why I don't think his approach fits my needs)
template<class... Outputters> class AggregateOutputter : public Generator<AggregateOutputter<Outputters...> > {
private:
typedef array<ostream *, sizeof...(Outputters)> DestArr;
DestArr destinations;
typedef typename DestArr::iterator DestArrIter;
struct OutputterHolder : public Outputters... {
OutputterHolder(vector<int>& v): Outputters(v)... {}
} outputter_holder;
template<class First, class... Rest> struct OutputHelper {
static void do_output(OutputterHolder *pthis, DestArrIter dest) {
**dest << *static_cast<First *>(pthis);
OutputHelper<Rest...>::do_output(pthis, ++dest);
}
};
template<class First> struct OutputHelper<First> {
static void do_output(OutputterHolder *pthis, DestArrIter dest) {
**dest << *static_cast<First *>(pthis);
}
};
public:
template<typename... OstreamStar> AggregateOutputter(unsigned length, OstreamStar... ostreams): Generator<AggregateOutputter<Outputters...> >(length), destinations{{ostreams...}}, outputter_holder(this->v) {
static_assert(sizeof...(OstreamStar) == sizeof...(Outputters), "number of outputters and destinations do not match");
}
friend ostream& operator<<(ostream& dummy_out, AggregateOutputter& outputter) {
OutputHelper<Outputters...>::do_output(&outputter.outputter_holder, outputter.destinations.begin());
// possibly write some logging info to dummy_out
return dummy_out;
}
};
// to use this:
ofstream fout("gv.gv");
cout << AggregateOutputter<FancyOutputter, SimpleDumpOutputter>(length, &fout, &cout);
The idea is that in addition to the output_helper in John's answer (which I have renamed to OutputHelper), there is another auxiliary struct called OutputterHolder, which inherits from all the Outputters. I've also used an array of ostream * to store the destination of output, and modified do_output to also take an iterator so that the correct ostream can be matched.
Importantly, to accompany the change, I've changed the protected member vector<int> v in Generator to a reference, ie vector<int>& v, so that the data structure in outputter_holder can be made to refer to the structure in AggregateOutputter instead. This also requires addition of another constructor in all outputters that takes vector<int>&. The original constructor that takes the length of v would now allocate the memory using new.
I'm not sure this solution I came up with is the best/most elegant solution though.
I want to do something like the following code shows:
class foo
{
private:
std::fstream* m_stream;
public:
foo(std::fstream* stream) : m_stream(stream) { }
foo& write(char const* s, std::streamsize count)
{
if (/*condition*/)
{
m_stream->write(s, count);
}
else
{
// ...
}
return *this;
}
foo& read(char* s, std::streamsize count)
{
if (/*condition*/)
{
m_stream->read(s, count);
}
else
{
// ...
}
return *this;
}
};
I would need to add the same behavior to all similar methods (e.g. put). This shouldn't be applied to file streams only, but all other stream classes. Is there any easy way to allow these functionality?
Many of the formatted output operators (operator<<) write directly to the underlying stream buffer. What you need to do in order to accomplish this in a general fashion is derive a class from std::basic_streambuf that forwards all data to another std::basic_streambuf, and then optionally create a minimal std::basic_ostream implementation to make using your stream buffer easier.
I wouldn't say this is particularly easy, though, but it's the only way to do this in a way that can affect all stream types.
Here is an example of a minimal stream buffer that forwards to another stream buffer (and performs some meaningless transformation just to demonstrate what you can do), and an accompanying stream:
#include <iostream>
#include <streambuf>
template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStreamBuf : public std::basic_streambuf<CharType, Traits>
{
public:
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
ForwardingStreamBuf(std::basic_streambuf<CharType, Traits> *baseStreamBuf)
: _baseStreamBuf(baseStreamBuf)
{
}
protected:
virtual int_type overflow(int_type c = traits_type::eof())
{
if( _baseStreamBuf == NULL )
return traits_type::eof();
if( traits_type::eq_int_type(c, traits_type::eof()) )
return traits_type::not_eof(c);
else
{
CharType ch = traits_type::to_char_type(c);
if( ch >= 'A' && ch <= 'z' )
ch++; // Do some meaningless transformation
return _baseStreamBuf->sputc(ch);
}
}
virtual int sync()
{
if( _baseStreamBuf == NULL )
return -1;
else
return _baseStreamBuf->pubsync();
}
private:
std::basic_streambuf<CharType, Traits> *_baseStreamBuf;
};
template<typename CharType, typename Traits = std::char_traits<CharType> >
class ForwardingStream : public std::basic_ostream<CharType, Traits>
{
public:
ForwardingStream(std::basic_ostream<CharType, Traits> &stream)
: std::basic_ostream<CharType, Traits>(NULL), _buffer(stream.rdbuf())
{
this->init(&_buffer);
}
ForwardingStreamBuf<CharType, Traits>* rdbuf() const
{
return &_buffer;
}
private:
ForwardingStreamBuf<CharType, Traits> _buffer;
};
This can be used very simply:
int main()
{
ForwardingStream<char> test(std::cout);
test << "Foo" << std::endl;
}
Which would output Gpp. I hope that helps you on your way.
Something like this?
template <class Stream>
class DecoratedStream {
public:
DecoratedStream(Stream* stream) : m_stream(stream) {}
DecoratedStream& write(const char* data, int count) {
m_stream->write(data, count);
}
};
If I understand you correctly, you want to decorate methods of any iostream. So just make your decorator take an iostream as decoratee (as opposed to an fstream, which is a subclass of iostream).
Having pointer inside a structure as your current approach is dangerous and error prone. Instead just derive such stream classes and implement basic constructors and wrap around your custom methods such as write().
template<typename StreamType>
class foo : StreamType
{
// wrapper constructors supporting StreamType() constructors
foo& write(char const* s, std::streamsize count)
{
//...
return *this;
}
};
Usage:
foo<fstream> obj;
obj.write(...);
The usual solution for this sort of problem is to use templates. There
aren't that many functions in an std::istream or and std::ostream
which need covering, and a good template member for<<and>>should
cover a lot of the cases. In most of the cases I've done this, I've
only offerred<<or>>`. (Generally speaking, I've not needed
bidirectional streams.)
As for handling other types of streams, just use std::iostream instead
of std::fstream. (In general, except when opening files, you
shouldn't see the fstream part.)
I am reluctant to say I can't figure this out, but I can't figure this out. I've googled and searched Stack Overflow, and come up empty.
The abstract, and possibly overly vague form of the question is, how can I use the traits-pattern to instantiate member functions? [Update: I used the wrong term here. It should be "policies" rather than "traits." Traits describe existing classes. Policies prescribe synthetic classes.] The question came up while modernizing a set of multivariate function optimizers that I wrote more than 10 years ago.
The optimizers all operate by selecting a straight-line path through the parameter space away from the current best point (the "update"), then finding a better point on that line (the "line search"), then testing for the "done" condition, and if not done, iterating.
There are different methods for doing the update, the line-search, and conceivably for the done test, and other things. Mix and match. Different update formulae require different state-variable data. For example, the LMQN update requires a vector, and the BFGS update requires a matrix. If evaluating gradients is cheap, the line-search should do so. If not, it should use function evaluations only. Some methods require more accurate line-searches than others. Those are just some examples.
The original version instantiates several of the combinations by means of virtual functions. Some traits are selected by setting mode bits that are tested at runtime. Yuck. It would be trivial to define the traits with #define's and the member functions with #ifdef's and macros. But that's so twenty years ago. It bugs me that I cannot figure out a whiz-bang modern way.
If there were only one trait that varied, I could use the curiously recurring template pattern. But I see no way to extend that to arbitrary combinations of traits.
I tried doing it using boost::enable_if, etc.. The specialized state information was easy. I managed to get the functions done, but only by resorting to non-friend external functions that have the this-pointer as a parameter. I never even figured out how to make the functions friends, much less member functions. The compiler (VC++ 2008) always complained that things didn't match. I would yell, "SFINAE, you moron!" but the moron is probably me.
Perhaps tag-dispatch is the key. I haven't gotten very deeply into that.
Surely it's possible, right? If so, what is best practice?
UPDATE: Here's another try at explaining it. I want the user to be able to fill out an order (manifest) for a custom optimizer, something like ordering off of a Chinese menu - one from column A, one from column B, etc.. Waiter, from column A (updaters), I'll have the BFGS update with Cholesky-decompositon sauce. From column B (line-searchers), I'll have the cubic interpolation line-search with an eta of 0.4 and a rho of 1e-4, please. Etc...
UPDATE: Okay, okay. Here's the playing-around that I've done. I offer it reluctantly, because I suspect it's a completely wrong-headed approach. It runs okay under vc++ 2008.
#include <boost/utility.hpp>
#include <boost/type_traits/integral_constant.hpp>
namespace dj {
struct CBFGS {
void bar() {printf("CBFGS::bar %d\n", data);}
CBFGS(): data(1234){}
int data;
};
template<class T>
struct is_CBFGS: boost::false_type{};
template<>
struct is_CBFGS<CBFGS>: boost::true_type{};
struct LMQN {LMQN(): data(54.321){}
void bar() {printf("LMQN::bar %lf\n", data);}
double data;
};
template<class T>
struct is_LMQN: boost::false_type{};
template<>
struct is_LMQN<LMQN> : boost::true_type{};
// "Order form"
struct default_optimizer_traits {
typedef CBFGS update_type; // Selection from column A - updaters
};
template<class traits> class Optimizer;
template<class traits>
void foo(typename boost::enable_if<is_LMQN<typename traits::update_type>,
Optimizer<traits> >::type& self)
{
printf(" LMQN %lf\n", self.data);
}
template<class traits>
void foo(typename boost::enable_if<is_CBFGS<typename traits::update_type>,
Optimizer<traits> >::type& self)
{
printf("CBFGS %d\n", self.data);
}
template<class traits = default_optimizer_traits>
class Optimizer{
friend typename traits::update_type;
//friend void dj::foo<traits>(typename Optimizer<traits> & self); // How?
public:
//void foo(void); // How???
void foo() {
dj::foo<traits>(*this);
}
void bar() {
data.bar();
}
//protected: // How?
typedef typename traits::update_type update_type;
update_type data;
};
} // namespace dj
int main() {
dj::Optimizer<> opt;
opt.foo();
opt.bar();
std::getchar();
return 0;
}
A simple solution might be to just use tag-based forwarding, e.g. something like this:
template<class traits>
void foo(Optimizer<traits>& self, const LMQN&) {
printf(" LMQN %lf\n", self.data.data);
}
template<class traits>
void foo(Optimizer<traits>& self, const CBFGS&) {
printf("CBFGS %d\n", self.data.data);
}
template<class traits = default_optimizer_traits>
class Optimizer {
friend class traits::update_type;
friend void dj::foo<traits>(Optimizer<traits>& self,
const typename traits::update_type&);
public:
void foo() {
dj::foo<traits>(*this, typename traits::update_type());
}
void bar() {
data.bar();
}
protected:
typedef typename traits::update_type update_type;
update_type data;
};
Or if you want to conveniently group several functions together for different traits, maybe something like this:
template<class traits, class updater=typename traits::update_type>
struct OptimizerImpl;
template<class traits>
struct OptimizerImpl<traits, LMQN> {
static void foo(Optimizer<traits>& self) {
printf(" LMQN %lf\n", self.data.data);
}
};
template<class traits>
struct OptimizerImpl<traits, CBFGS> {
static void foo(Optimizer<traits>& self) {
printf("CBFGS %d\n", self.data.data);
}
};
template<class traits = default_optimizer_traits>
class Optimizer{
friend class traits::update_type;
friend struct OptimizerImpl<traits>;
public:
void foo() {
OptimizerImpl<traits>::foo(*this);
}
// ...
};
I think template specialization is a step in the right direction. This doesn't work with functions so I switched to classes. I changed it so it modifies the data. I'm not so sold on the protected members and making friends. Protected members without inheritance is a smell. Make it public or provide accessors and make it private.
template <typename>
struct foo;
template <>
struct foo<LMQN>
{
template <typename OptimizerType>
void func(OptimizerType& that)
{
printf(" LMQN %lf\n", that.data.data);
that.data.data = 3.14;
}
};
template <>
struct foo<CBFGS>
{
template <typename OptimizerType>
void func(OptimizerType& that)
{
printf(" CBFGS %lf\n", that.data.data);
}
};
template<class traits = default_optimizer_traits>
class Optimizer{
public:
typedef typename traits::update_type update_type;
void foo() {
dj::foo<typename traits::update_type>().func(*this);
}
void bar() {
data.bar();
}
update_type data;
};
It would be trivial to define the traits with #define's and the member functions with #ifdef's and macros. But that's so twenty years ago.
Although it may be worth learning new methods, macros are often the simplest way to do things and shouldn't be discarded as a tool just because they're "old". If you look at the MPL in boost and the book on TMP you'll find much use of the preprocessor.
Here's what I (the OP) came up with. Can you make it cooler?
The main Optimizer template class inherits policy-implementation classes. It gives those classes access to the Optimizer's protected members that they require. Another Optimizer template class splits the manifest into its constituent parts and instantiates the main Optimizer template.
#include <iostream>
#include <cstdio>
using std::cout;
using std::endl;
namespace dj {
// An updater.
struct CBFGS {
CBFGS(int &protect_)
: protect(protect_)
{}
void update () {
cout << "CBFGS " << protect << endl;
}
// Peek at optimizer's protected data
int &protect;
};
// Another updater
struct LMQN {
LMQN(int &protect_)
: protect(protect_)
{}
void update () {
cout << "LMQN " << protect << endl;
}
// Peek at optimizer's protected data
int &protect;
};
// A line-searcher
struct cubic_line_search {
cubic_line_search (int &protect2_)
: protect2(protect2_)
{}
void line_search() {
cout << "cubic_line_search " << protect2 << endl;
}
// Peek at optimizer's protected data
int &protect2;
};
struct default_search_policies {
typedef CBFGS update_type;
typedef cubic_line_search line_search_type;
};
template<class Update, class LineSearch>
class Opt_base: Update, LineSearch
{
public:
Opt_base()
: protect(987654321)
, protect2(123456789)
, Update(protect)
, LineSearch(protect2)
{}
void minimize() {
update();
line_search();
}
protected:
int protect;
int protect2;
};
template<class Search_Policies=default_search_policies>
class Optimizer:
public Opt_base<typename Search_Policies::update_type
, typename Search_Policies::line_search_type
>
{};
} // namespace dj
int main() {
dj::Optimizer<> opt; // Use default search policies
opt.minimize();
struct my_search_policies {
typedef dj::LMQN update_type;
typedef dj::cubic_line_search line_search_type;
};
dj::Optimizer<my_search_policies> opt2;
opt2.minimize();
std::getchar();
return 0;
}
Your use of enable_if is somewhat strange. I've seen it used it only 2 ways:
in place of the return type
as a supplementary parameter (defaulted)
Using it for a real parameter might cause the havoc.
Anyway, it's definitely possible to use it for member functions:
template<class traits = default_optimizer_traits>
class Optimizer{
typedef typename traits::update_type update_type;
public:
typename boost::enable_if< is_LQMN<update_type> >::type
foo()
{
// printf is unsafe, prefer the C++ way ;)
std::cout << "LQMN: " << data << std::endl;
}
typename boost::enable_if< is_CBFGS<update_type> >::type
foo()
{
std::cout << "CBFGS: " << data << std::endl;
}
private:
update_type data;
};
Note that by default enable_if returns void, which is eminently suitable as a return type in most cases. The "parameter" syntax is normally reserved for the constructor cases, because you don't have a return type at your disposal then, but in general prefer to use the return type so that it does not meddle with overload resolution.
EDIT:
The previous solution does not work, as noted in the comments. I could not find any alternative using enable_if, only the "simple" overload way:
namespace detail
{
void foo_impl(const LMQN& data)
{
std::cout << "LMQN: " << data.data << std::endl;
}
void foo_impl(const CBFGS& data)
{
std::cout << "CBFGS: " << data.data << std::endl;
}
} // namespace detail
template<class traits = default_optimizer_traits>
class Optimizer{
typedef typename traits::update_type update_type;
public:
void foo() { detail::foo_impl(data); }
private:
update_type data;
};
It's not enable_if but it does the job without exposing Optimizer internals to everyone. KISS ?
I'm trying to implement a generic toString() function that would work on all types. All our internal classes derive from Abstract which includes a signature for toString(). In other words, all our internal classes have in some form, a toString method.
The problem is, the primitive types (int, char, double..) don't have a native toString function. But we do have a utility function that calls the lexical_cast to give back the string value of the primitive. We don't want a whole bunch of if statements depending So I'm trying to create a templated utility class that would do the job.
My first hack at this is the below:
template<class T>
class ObjectToString {
public:
string objectToString(T value) {
iil::stringUtils::StringSp ret(stringUtils::valueToString<T>(value));
return ret;
}
};
template<>
class ObjectToString <Abstract<T>*> {
public:
iil::stringUtils::StringSp objectToString(Abstract<T>* value) {
return iil::stringUtils::StringSp(new std::string("AAAA"));
}
};
The problem now is, since Abstract is a templated class, it needs the template value T. I have no idea how to set that. Could anyone advise?
How about simply providing a specialization for lexical_cast?
template<> string lexical_cast(Abstract* obj)
{
return obj->toString();
}
Isn't your problem much simpler? On all Abstract objects you know what to do, so all you need is to provide overloaded functions for built-in types:
string getAsString(Abstract *obj)
{
return obj->toString();
}
string getAsString(int x)
{
return intToStr(x);
}
string getAsString(double x)
{
return doubleToStr(x);
}
etc, where you implement intToStr() and doubleToStr() as appropriate.
This has been dealt with at length by Matthew Wilson in the form of shims, as described in this Dr Dobb's article, and the books Imperfect C++ and Extended STL. They underlie the technology that allow the FastFormat and Pantheios libraries to deal with argument types generically.
You just don't think in C++ way. C++ already has "toString" that is called operator<< to std::ostream. You need to implement it for your classes.
And if you want to support inheritence, do this:
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <string>
class streamable {
public:
virtual void stream(std::ostream &) const = 0;
};
std::ostream &operator<<(std::ostream &out,streamable const &obj)
{
obj.stream(out);
return out;
}
// Now anything derived from streamable can be written to std::ostream
// For example:
class bar : public streamable {
int x;
int y;
public:
bar(int a,int b) : x(a),y(b){}
virtual void stream(std::ostream &out) const { out<<x<<":"<<y; }
};
int main()
{
bar b(1,3);
std::cout<< b << std::endl;
// and converted to string
std::string str=boost::lexical_cast<std::string>(b);
std::cout<< str <<std::endl;
}
This is C++ way, and as you can see you have boost::lexical_cast for free.
EDIT for your case:
template<typename T>
class Abstract {
public:
virtual void stream(std::ostream &) const = 0;
};
template<typename T>
std::ostream &operator<<(std::ostream &out,Abstract<T> const &obj)
{
obj.stream(out);
return out;
}
Now if you don't like boost::lexical_cast, implement string_cast as simple as
template<typename T>
std::string string_cast(T const &obj)
{
std::ostringstram ss;
ss<<obj;
return ss.str();
}