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.
Related
I used to define my template requirement through abstract class, e.g.
#include <iostream>
#include <random>
/// Generic interface
template<typename A, typename B>
struct Interface {
virtual A callback_A(const std::vector<A>& va) = 0;
virtual const B& callback_B() = 0;
};
/// Mixin style, used to "compose" using inheritance at one level, no virtual
struct PRNG_mt64 {
std::mt19937_64 prng;
explicit PRNG_mt64(size_t seed) : prng(seed) {};
};
/// Our implementation
template<typename A>
struct Implem :
public Interface<A, std::string>,
public PRNG_mt64 {
std::string my_string{"world"};
explicit Implem(size_t seed) : PRNG_mt64(seed) {}
A callback_A(const std::vector<A>& a) override { return a.front(); }
const std::string& callback_B() override { return my_string; }
};
/// Function using our type. Verification of the interface is perform "inside" the function
template<typename T>
void use_type(T& t) {
auto& strings = static_cast<Interface<std::string, std::string>&>(t);
std::cout << strings.callback_A({"hello"}) << " " << strings.callback_B() << std::endl;
auto& prng = static_cast<PRNG_mt64&>(t).prng;
std::uniform_real_distribution<double> dis(0.0, 1.0);
std::cout << dis(prng) << std::endl;
}
int main(int argc, char **argv) {
size_t seed = std::random_device()();
Implem<std::string> my_impl(seed);
use_type(my_impl);
}
One benefit of using the asbtract class is the clear specification of the interface, easily readable. Also, Implem has to confom to it (we cannot forget the pure virtual).
A problem is that the interface requirement is hidden in the static cast (that comes from my real use case where a composite "state" is used by several polymorphic components - each component can cast the state to only see what it needs to see). This is "solved" by concepts (see below).
Another one is that we are using the virtual mechanism when we have no dynamic polymorphism at all, so I would like to get rid of them. What is the best way to convert this "interface" into concept?
I came up with this:
#include <iostream>
#include <random>
/// Concept "Interface" instead of abstract class
template<typename I, typename A, typename B>
concept Interface = requires(I& impl){
requires requires(const std::vector<A>& va){{ impl.callback_A(va) }->std::same_as<A>; };
{ impl.callback_B() } -> std::same_as<const B&>;
};
/// Mixin style, used to "compose" using inheritance at one level, no virtual
struct PRNG_mt64 {
std::mt19937_64 prng;
explicit PRNG_mt64(size_t seed) : prng(seed) {};
};
/// Our implementation
template<typename A>
struct Implem : public PRNG_mt64 {
std::string my_string{"world"};
/// HERE: requires in the constructor to "force" interface. Can we do better?
explicit Implem(size_t seed) requires(Interface<Implem<A>, A, std::string>): PRNG_mt64(seed) {}
A callback_A(const std::vector<A>& a) { return a.front(); }
const std::string& callback_B() { return my_string; }
};
/// Function using our type. Verification of the interface is now "public"
template<Interface<std::string, std::string> T>
void use_type(T& t) {
std::cout << t.callback_A({"hello"}) << " " << t.callback_B() << std::endl;
auto& prng = static_cast<PRNG_mt64&>(t).prng;
std::uniform_real_distribution<double> dis(0.0, 1.0);
std::cout << dis(prng) << std::endl;
}
int main(int argc, char **argv) {
size_t seed = std::random_device()();
Implem<std::string> my_impl(seed);
use_type(my_impl);
}
Questions:
Is that actually the thing to do in the first place? I saw several posts on the internet explaning concepts, but they are always so shallow that I'm afraid I'll miss something regarding perfect forwarding, move, etc...
I used a requires requires clause to keep function arguments close to their usage (useful when having many methods). However, the "interface" information is now hard to read: can we do better?
Also, the fact that Implem implements the interface is now the part that is "hidden" inside the class. Can we make that more "public" without having to write another class with CRTP, or limiting the boilerplate code as much as possible?
Can we do better for the "mixin" part PRNG_mt64? Ideally, turning this into a concept?
Thank you!
Your pre-C++20 approach is pretty bad, but at least it sounds like you understand the problems with it. Namely, you're paying 8 bytes for a vptr when you don't need it; and then strings.callback_B() is paying the cost of a virtual call even though you could be calling t.callback_B() directly.
Finally (this is relevant, I promise), by funneling everything through the base-class reference strings, you're taking away Implem's ability to craft a helpful overload set. I'll show you a simpler example:
struct Interface {
virtual int lengthOf(const std::string&) = 0;
};
struct Impl : Interface {
int lengthOf(const std::string& s) override { return s.size(); }
int lengthOf(const char *p) { return strlen(p); }
};
template<class T>
void example(T& t) {
Interface& interface = t;
static_assert(!std::same_as<decltype(interface), decltype(t)>); // Interface& versus Impl&
int x = interface.lengthOf("hello world"); // wastes time constructing a std::string
int y = t.lengthOf("hello world"); // does not construct a std::string
}
int main() { Impl impl; example(impl); }
The generic-programming approach would look like this, in C++20:
template<class T>
concept Interface = requires (T& t, const std::string& s) {
{ t.lengthOf(s) } -> convertible_to<int>;
};
struct Impl {
int lengthOf(const std::string& s) override { return s.size(); }
int lengthOf(const char *p) { return strlen(p); }
};
static_assert(Interface<Impl>); // sanity check
template<Interface T>
void example(T& t) {
Interface auto& interface = t;
static_assert(std::same_as<decltype(interface), decltype(t)>); // now both variables are Impl&
int x = interface.lengthOf("hello world"); // does not construct a std::string
int y = t.lengthOf("hello world"); // does not construct a std::string
}
int main() { Impl impl; example(impl); }
Notice that there is no way at all to get back the "funneling" effect you had with the base-class approach. Now there is no base class, the interface variable itself is still statically a reference to an Impl, and calling lengthOf will always consider the full overload set provided by the Impl. This is a good thing for performance — I think it's a good thing in general — but it is radically different from your old approach, so, be careful!
For your callback_A/B example specifically, your concept would look like
template<class T, class A, class B>
concept Interface = requires (T& impl, const std::vector<A>& va) {
{ impl.callback_A(va) } -> std::same_as<A>;
{ impl.callback_B() } -> std::same_as<const B&>;
};
In real life I would very strongly recommend changing those same_ases to convertible_tos instead. But this code is already very contrived, so let's not worry about that.
In C++17 and earlier, the equivalent "concept" (type-trait) definition would look like this (complete working example in Godbolt). Here I've used a macro DV to shorten the boilerplate; I wouldn't actually do that in real life.
#define DV(Type) std::declval<Type>()
template<class T, class A, class B, class>
struct is_Interface : std::false_type {};
template<class T, class A, class B>
struct is_Interface<T, A, B, std::enable_if_t<
std::is_same_v<int, decltype( DV(T&).callback_A(DV(const std::vector<A>&)) )> &&
std::is_same_v<int, decltype( DV(T&).callback_B() )>
>> : std::true_type {};
In some code that I was reading, I found the usage of empty struct like so:
struct input_iterator_tag { };
struct bidirectional_iterator_tag { };
struct random_access_iterator_tag { };
So in the rest of the code, it was used as what they call tag dispatching.
I was wondering if there is other usage of empty structs.
from an older post I saw that :
three major reasons we use empty structs in C++ are:
a base interface
a template parameter
a type to help overload resolution. (tag dispatching if I am not wrong)
Could someone explain that please?
a type to help overload resolution. (tag dispatching if I am not wrong)
When you want to use a complex template specialization pattern on some function, you don't try to go at it directly, but rather write:
template <typename T1, typename T2, other things maybe>
int foo(T1 param1, T2 param2 and so on)
{
using tag = put your complex stuff here, which produces an empty struct
detail::foo_impl(tag, std::forward<T1>(param1), std::forward<T2>(param2) and so on);
}
Now, the compiler doesn't have to decide between competing choices of template specialization, since with different tags you get incompatible functions.
a base interface
struct vehicle {
// common members and methods,
// including (pure) virtual ones, e.g.
virtual std::size_t num_maximum_occupants() = 0;
virtual ~vehicle() = default;
};
namespace mixins {
struct named { std::string name; };
struct wheeled { int num_wheels; public: rev() { }; };
} // namespace mixins
struct private_sedan : public vehicle, public wheeled, named {
// I dunno, put some car stuff here
//
// and also an override of `num_maximum_occupants()`
};
Making the base struct completely empty is perhaps not that common, but it's certainly possible if you use mixins a lot. And you could check for inheritance from vehicle (although I'm not sure I'd do that).
a template parameter
Not sure what this means, but venturing a guess:
template <typename T>
struct foo { };
template <typename T, typename N>
struct foo<std::array<T, N>> {
int value = 1;
};
If you now use foo<T>::value in a function, it will work only if T is int with few (?) exceptions.
I also tried to come up with examples:
as a base interface
// collection of very abstract vehicles
#include <vector>
struct Vehicle {};
struct Car : Vehicle {
int count_of_windows;
};
struct Bike : Vehicle {
int size_of_wheels;
};
std::vector<Vehicle> v{Bike{}, Car{}};
as a template parameter
// print same number in 3 different formats
#include <iostream>
struct dec {};
struct hex {};
struct octal {};
template<typename HOW = dec>
void print_me(int v);
template<>
void print_me<dec>(int v) {
auto f = std::cout.flags();
std::cout << std::dec << v << std::endl;
std::cout.flags(f);
}
template<>
void print_me<hex>(int v) {
auto f = std::cout.flags();
std::cout << std::hex << v << std::endl;
std::cout.flags( f );
}
template<>
void print_me<octal>(int v) {
auto f = std::cout.flags();
std::cout << std::oct << v << std::endl;
std::cout.flags(f);
}
int main() {
print_me(100);
print_me<hex>(100);
print_me<octal>(100);
}
a type to help overload resolution
// add a "noexcept" qualifier to overloaded function
// the noexcept version typically uses different functions
// and a custom "abort" handler
#include <iostream>
struct disable_exceptions {};
void is_number_1() {
int v;
std::cin >> v;
if (v != 1) {
throw new std::runtime_error("AAAA");
}
}
void is_number_1(disable_exceptions) noexcept {
int v;
// use C function - they don't throw
if (std::scanf("%d", &v) != 1) {
std::abort();
}
if (v != 1) {
std::abort();
}
}
int main() {
is_number_1();
is_number_1(disable_exceptions());
}
The example about "tag dispatching" can be found on cppreference iterator_tags. The iterator_category() member of an iterator is used to pick a different overload. That way you could write a different algorithm if for example iterator is forward_iterator, where you can only go forward, or it is a bidirectional_iterator, where your algorithm could change because you may walk back.
I am using a container to hold a list of pointers to anything:
struct Example {
std::vector<boost::any> elements;
}
To insert elements in this container, I had written a couple of helper functions (members of the struct Example):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
Now, I would like to insert elements only when they are not present in this container. To do this, I thought that I would only need to call search over elements with an appropriate comparator function. However, I do not know how to compare the boost::any instances.
My question:
Knowing that my boost::any instances always contain a pointer to something; is it possible to compare two boost::any values?
update
I thank you for your answers. I have also managed to do this in a probably unsafe way: using boost::unsafe_any_cast to obtain a void** and comparing the underlying pointer.
For the moment, this is working fine. I would, however, appreciate your comments: maybe this is a big mistake!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if ( any_compare(a,*it) ) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
You cannot directly provide it, but you can actually use any as the underlying type... though for pointers it's pointless (ah!)
struct any {
std::type_info const& _info;
void* _address;
};
And a templated constructor:
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t))
{
}
This is, basically, boost::any.
Now we need to "augment" it with our comparison mechanism.
In order to do so, we'll "capture" the implementation of std::less.
typedef bool (*Comparer)(void*,void*);
template <typename T>
bool compare(void* lhs, void* rhs) const {
return std::less<T>()(*reinterpret_cast<T*>(lhs), *reinterpret_cast<T*>(rhs));
}
template <typename T>
Comparer make_comparer(T*) { return compare<T>; }
And augment the constructor of any.
struct any {
std::type_info const& _info;
void* _address;
Comparer _comparer;
};
template <typename T>
any::any(T* t):
_info(typeid(*t)),
_address(dynamic_cast<void*>(t)),
_comparer(make_comparer(t))
{
}
Then, we provided a specialization of less (or operator<)
bool operator<(any const& lhs, any const& rhs) {
if (lhs._info.before(rhs._info)) { return true; }
if (rhs._info.before(lhs._info)) { return false; }
return (*lhs._comparer)(lhs._address, rhs._address);
}
Note: encapsulation, etc... are left as an exercise to the reader
The only easy way to do this I can think of involves hardcoding support for the types that you're storing in the any instances, undermining much of the usefulness of any...
bool equal(const boost::any& lhs, const boost::any& rhs)
{
if (lhs.type() != rhs.type())
return false;
if (lhs.type() == typeid(std::string))
return any_cast<std::string>(lhs) == any_cast<std::string>(rhs);
if (lhs.type() == typeid(int))
return any_cast<int>(lhs) == any_cast<int>(rhs);
// ...
throw std::runtime_error("comparison of any unimplemented for type");
}
With C++11's type_index you could use a std::map or std::unordered_map keyed on std::type_index(some_boost_any_object.type()) - similar to what Alexandre suggests in his comment below.
If you can change type in container, there is Boost.TypeErasure. It provides easy way to customize any. For example I'm using such typedef for similar purpose:
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp>
using Foo = boost::type_erasure::any<
boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::equality_comparable<>,
boost::type_erasure::typeid_<>,
boost::type_erasure::relaxed
>
>;
Foo behaves exactly the same as boost::any, except that it can be compared for equality and use boost::type_erasure::any_cast instead of boost::any_cast.
There is no need to create new class. Try to use xany https://sourceforge.net/projects/extendableany/?source=directory xany class allows to add new methods to any's existing functionality. By the way there is a example in documentation which does exactly what you want (creates comparable_any).
Maybe this algorithm come in handy >
http://signmotion.blogspot.com/2011/12/boostany.html
Compare two any-values by type and content. Attempt convert string to number for equals.
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 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..