I have a number of algorithms for community detection on graphs that I want to now visualise them. This visualisation requires me to 'hijack' these algorithms while they execute and log what they are doing. Specifically this will mean passing a reference to a std::vector<graph_partition> as an argument to these algorithms, and appending to that vector as the algorithm proceeds.
Therefore to each algorithm (which are typically just functions), I would need to add a further argument for the &std::vector<graph_partition>, and one or two lines of code for the logging.
I will not always want/need to log however, and so doing this in an intelligent way has proved non-trivial. I have thought of:
Write separate logging versions of each algorithm: The problem here is that I'll be repeating myself massively, since 95% of the logging and non-logging functions will be the same. You could say my code should be so modular that no repetition should occur, but in practice unless I have lots of tiny trivial functions I would have to repeat myself.
Have single function with a conditional argument to decide whether to log or not: Problem is what do I pass for &std::vector<graph_partition> when I don't want to use it? Also (probably minuscule) runtime hit of continuously evaluating conditional.
Some macro wizardry: Macros are a bit evil and would prefer to avoid them if possible.
Just log by default, discard if I don't need it: Convenient but wasteful, both in terms of runtime and space.
Any ideas or thoughts on these would be appreciated.
If you fancy using templates, I don't think you really need variadic templates. If you're happy to recompile in order to switch logging on and off:
struct NoLogging {
void log(const graph_partition &) {}
};
struct Logging {
std::vector<graph_partition> vec;
void log(const graph_partition &p) {
vec.push_back(p);
}
};
template <typename Logger>
void some_algorithm(Logger &logger) {
// do some stuff
logger.log(something);
}
// optionally, for convenience
void some_algorithm() {
NoLogging l;
some_algorithm(l);
}
// user writes:
some_algorithm();
// or
Logging l;
some_algorithm(l);
// do something with l.vec
The difference between this and "just log by default, even if I don't need it", is that an even vaguely decent compiler will completely remove the calls to log in some_algorithm<NoLogging>, because it can see that they do nothing.
If you don't want to have to recompile, you could have a runtime switch between the two different sets of instantiations - it may or may not be convenient to do this via some polymorphic interface that provides all the algorithms and has two derived classes, from a template like so:
template <typename Logger>
struct ConcreteAlgorithms : public Algorithms {
Logger logger;
static void some_algorithm() {
::some_algorithm(logger);
}
// more algorithms
};
Algorithms *get_algorithms(bool with_logging) {
if (with_logging) {
return new ConcreteAlgorithms<Logging>;
} else {
return new ConcreteAlgorithms<NoLogging>;
}
}
However, at this point you're going to have the code bloat of two different versions of the algorithms, so you might prefer to make the logger polymorphic and take the (probably tiny) runtime overhead instead, as per Mark's answer.
Pass a pointer to a parent logging class to each function. Have a child of the logging class that implements the logging function as a do-nothing, and use that one when you don't need logging. The real logging class would also be a child, and would contain the vector or a reference to it.
Related
At work, I have come across code which basically looks like that:
#include <iostream>
using namespace std;
enum e_Specialization {
Specialization_A,
Specialization_B
};
template<e_Specialization>
class TemplatedBase {
public:
string foo() { return "TemplatedBase::foo"; }
};
template<>
string TemplatedBase<Specialization_A>::foo() { return "TemplatedBase<Specialization_A>:foo"; }
int main() {
TemplatedBase<Specialization_A> o;
cout << o.foo() << endl;
return 0;
}
which outputs
TemplatedBase<Specialization_A>:foo
I haven't been able to find any discussion on this technique anywhere.
The code's creator argued mostly from the optimization side of things, that no virtual dispatch happens. In our case this optimization is not necessary, but I see how it could be useful.
My questions are:
Is this technique documented anywhere and does it have a name?
In comparison to specialization by inheritance, are there any advantages to this at all?
3. How does this relate to CRTP? To me it seems that the same is achieved, with all pros and cons of CRTP.
As far as whether the technique is documented (and if you are doing this with C++11 or later, please use an enum class), it's a fairly common technique to template on an enum or a boolean and then do your specializations.
One clear difference is that with this technique, you obviously can't add more specializations without modifying the primary code. An enum (or enum class) only has so many values. That could be either a good or bad thing, depending on whether you want it to be centrally tracked. But that could easily be changed by templating on a class and encapsulating it, a third option which isn't quite this technique nor does it involve public inheritance.
This technique has its biggest advantage, IMHO, in that you have the option to implement things inline. For example:
template<e_Specialization e>
class TemplatedBase {
public:
void bar() {
// code
if (e == Specialization_A) {
...
}
// code
}
};
I see this a lot with classes that are known from the outset to be in a performance critical path. There could be a boolean variable that controls whether or not intrusive performance profiling occurs. Because these branches are known at compile time, they are trivially optimized. This is a good way to do it because you can still use both versions of the class in the same build (e.g. run unit tests on both).
Another difference compared to inheritance, is that derived classes can easily add state if they need to. This technique as it stands would require specializing the whole class to add state. Again, this could be good or bad; a more constrained design is good if you don't need to break those constraints. And you can easily change the design to enable adding extra state:
template <e_Specialization e>
struct ExtraState {};
template <e_Specialization e>
class TemplatedBase : private ExtraState<e> {
...
A third, minor example, is that you aren't exposing any inheritance relationship. This is mostly small, but remember that you can get things like slicing or even implicit reference/pointer conversion. This is a pretty strict win for this technique.
In sum I would say that:
It's a win if you utilize the ability to implement something once and write the differences inline with no perf penalty
It's a win if you want to be explicit in your design about there being a limited number of implementations.
If neither of those are true then the design is a bit unorthodox and a little more complex compared to just using inheritance, although it doesn't really have any strong technical disadvantage. So if you have a good number of junior devs around, this code might be harder to read.
I'm writing a C++ hardware abstraction layer (HAL), which needs to be as fast as possible.
Polymorphism offers the best API, but Virtual Table lookups really kill the speed of the code.
This lead me to using templates in conjunction with policies to get compile-time polymorphism. But because templates with different arguments get instantiated as completely different types, I can not use them interchangeably in function calls unless the function is a template as well.
However, I dont want to force the user of my HAL library to write all function as templates because I have used templates.
For illustration purposes, suppose this is my HAL:
template<typename T_POLICY>
class I2CManager {
public:
void send(uint8_t data) {
T_POLICY::send(data);
++sent_data;
}
private:
int sent_data; // Just to illustrate that I2CManager has state
};
class I2C1 {
static void send(uint8_t data) { /* Run some code here */ }
};
class I2C2 {
static void send(uint8_t data) { /* Run other code here */ }
};
// OTHER HW
template<typename T_POLICY>
class UARTManager { ··· };
class UART1 { ··· };
class UART2 { ··· };
template<typename T_POLICY>
class TIMERManager { ··· };
class TIMER1A { ··· };
class TIMER1B { ··· };
This works and I can now create a I2CManager with different policies, such as follows. I can even have several I2CManagers running with different policies at the same time.
I2CManager<I2C1> i2c1;
I2CManager<I2C2> i2c2;
i2c1.send(0x11); // This works
i2c2.send(0x11); // This also works
Now, i2c1 and i2c2 have the same public methods, yet they are not interchangeable. Consequently, the user of my HAL library is forced to use templates as well.
// THIS DOES NOT WORK
void foo(I2CManager m) { m.send(0x11); }
foo(my_manager_1);
// BUT THIS WORKS
template<typename T>
void foo(I2CManager<T> m) { m.send(0x11); }
foo(i2c1);
Can I somehow get compile-time polymorphism but allow the end-user to treat it as if it was normal polymorphism? I don't care if the inner code in my library gets ugly or difficult to read for the sake of speed, but the API has to be as simple and intuitive as possible.
Actually, I want foo() to be specialized (and replicated in code) for the different parameters as if it was a template, but I don't want the user of my library to notice it is a template function. Altought alternatives to templates are also welcome.
I don't know if this is even possible, but I have read something about concepts which will appear in the next C++ standard. I want compile-time polymorphism, but as userfrliendly as runtime polymorhism.
Considerations:
Because I'm interfacing HW, each instantiation of my HWManagers with
different policies will be unique (i.e. There is only one
HWManager instance, and one HWManager instance,
and may or may not exist simultaneously).
All instances are created by the library as global variables, and are
not heapable.
All policy methods are extremely short, so having multiple unique
instances due to templates is preferable to Virtual Tables for the
sake of execution speed.
Code size does not matter (its for embedded systems), but RAM usage
and execution speed does. I need as much as possible to be solved
during compile time. Again, I'm willing to have a over-bloated
executable for the sake of avoiding run-time resolutions.
Only up to C++03 supported
Code example edited
All instances are created by the library as global variables, and are not heapable.
You mean something like this, right?
static HWManager<DrierPolicy> drierManager;
static HWManager<FridgePolicy> fridgeManager;
Then, what wrong with letting the user know about them and allow her/him to use those directly like:
drierManager.doStuff();
fridgeManager.doStuff();
And then...
Because I'm interfacing HW, each instantiation of my HWManagers with different policies will be unique
Then why implement the doStuff method as instance ones? Aren't some static methods good enough?
(those are questions, not critiques. Yes, I know, this is hardly an answer - it may be one though - but I needed the extra formatting that the comments do not provide)
I often run into the problems associated with SubType Polymorphism, I'm looking for an elegant solution I may not already be aware of.
Here is a simple inheritence hierarchy:
struct BaseClass {
virtual ~BaseClass() = 0;
std::string name;
};
template <T>
struct DerivedClass
{
DerivedClass(const std::string& _name): name(_name) { }
};
Now I might create lots of these DerivedClass instances with different names and template types and store them in an array using their BaseClass.
std::vector<BaseClass*> array;
array.push_back(new DerivedClass<TABC>("abc"));
array.push_back(new DerivedClass<TDEF>("def"));
...
This is pretty standard runtime polymorphism.
However, when I have a new layer of functionality that is type-specific to add and don't want this new layer to be coupled in both directions, I end up having to do something like this:
template <typename T>
void method(DerivedClass<T>* object) { }
void callMethod(BaseClass* object)
{
// this is the logic I'm trying to move up a layer
if (object->name == "abc") method<TABC>(object);
else if (object->name == "def") method<TDEF>(object);
}
Each of these methods has to have the same list of run-time strings to compile-time types to convert, which means adding a new type requires a lot of changes.
If I was to assume the new layer would only support specific options known at compile-time (as is the case here anyway), then it would be feasible to add new types at runtime, but not be able to use them in this layer, which would be fine.
My current thinking is if I was to introduce a virtual method to the class hierarchy that took a function pointer, I could register the function pointers for each method in the second layer based on specific compile-time types (ideally only specified once), kind of like a double dispatch type method.
Any thoughts, suggestions?
You need that link to call the specific template version based on a string, the best you can do is have a dictionary of string->lambda function and use the string as a lookup to get a function<> to call. This avoids the nested ifs and it's relatively easy to maintain, both at compile time (the default list) and at runtime (any changes are just array changes).
Rather than steal Sean Parent's thunder I'll direct you to this talk which will show you how to achieve this cleanly, safely and simply.
The technique is called 'polymorphism as an implementation detail'. It has transformed the way I write code.
https://channel9.msdn.com/Events/GoingNative/2013/Inheritance-Is-The-Base-Class-of-Evil
Given the following, working code.
#include <iostream>
template<class Detail>
class AbstractLogger
{
public:
static void log(const char* str) {
Detail::log_detailled(str);
}
};
class Logger : public AbstractLogger<Logger>
{
public:
static void log_detailled(const char* str) {
std::cerr << str << std::endl;
}
};
int main(void)
{
AbstractLogger<Logger>::log("main function running!");
return 0;
}
Now, I want to put AbstractLogger into a library, and let the library user define his own logger, like the Logger class here. This has one drawback: AbstractLogger<Logger> can not be used inside the library, since the library can not know Logger.
Notes:
Please no virtual functions or questions why not. Also, I am aware of the similar problem that "static virtual" members are invalid. Maybe, there is a workaround in CRTP :)
C++11 will be interesting, however, I need "usual" C++.
If what you mean is that you want to have a library that uses this as a logging mechanism without knowing the exact instantiating type, I would advice against it.
The only way of doing it while meeting your other requirements (i.e. no virtual functions) is that all your functions/types in the library that need to log are converted into templates that take the Logger type. The net result is that most of your interface becomes a template (although you can probably move a good amount of the implementation to non-templated code, it will make your life much harder than needed, and it will still generate a much larger binary).
If your concern with virtual functions is performance, then you should reconsider your approach and the problems it brings. In particular, logging is expensive. Most logging libraries tackle it by optimizing the non-logging case (by means of macros that avoid calling the logger if the log level/group/... are not enabled), but still leave dynamic dispatch for the actual writting. The cost of the dynamic dispatch is negligible compared with the cost of writing to the console, or a file, or even with the cost of generating the message that will be logged (I am assuming that you not only log literal strings)
The usual approach is to code against a concept, while providing helpers so that users may easily produce types that satisfy one or more of those concepts. As an example, something like boost::iterator_facade is a CRTP helper that makes it easier for a user to write an iterator. Then, that iterator can be used anywhere an iterator is accepted -- for instance in the range constructor of std::vector. Notice how that particular constructor has no foreknowledge of the user-defined type.
In your case, AbstractLogger would be the CRTP helper. The missing piece would be to define e.g. a logger concept. As a result, notice that everything that needs a logger either needs to be implemented as a template or you need a type-erasing container to hold arbitrary loggers.
Concept checks (like those provided by Boost) are convenient for this kind of programming, since they allow to represent a concept with actual code.
Template classes can't be 'put in a library' since they are instantiated by the compiler as specializations of their template parameters.
You may put parameter independent stuff used in the template implementation into a library though.
I would like to add a log to my application. I've picked a logging library but I'd like to be able to switch to a different library without having to alter any code that uses logging.
Therefore, I need some sort of logging wrapper that is flexible enough to utilize pretty much any underlying logging library's functionality.
Any suggestions for such a wrapper's design?
EDIT: one feature I must have in this wrapper is component tagging. I want my algorithm class to have "X:" appear ahead of its log lines, and my manager class to have "Y:" appear. How to propagate this these tags onto the underling log and how to build the component tag naming mechanism is one major design question here.
Your best bet is to make the interface as simple as possible. Completely separate the logging user's interface from how the logging actually gets implemented.
Cross-cutting concerns always are expensive to maintain, so making things any more complicated will make you hate life.
Some library only wants something simple like this:
void logDebug(const std::string &msg);
void logWarning(const std::string &msg);
void logError(const std::string &msg);
They shouldn't add or specify any more context. No one can use the information anyway, so don't over design it.
If you start adding more information to your logging calls it makes it harder to reuse the client code that uses it. Usually you will see this surface when components are used at different levels of abstraction. Especially when some low level code is providing debug information that is only relevant to higher levels.
This doesn't force your logging implementation (or even the interface the logging implementation conforms to!) into anything either, so you can change it whenever.
UPDATE:
Insofar as the tagging, that is a high level concern. I'm going to speculate that it doesn't belong in the log, but that is neither here nor there.
Keep it out of the logging message specification. Low level code shouldn't give a flying truck who you or your manager is.
I don't know how you specify X or Y in your example. How you do that isn't really obvious from the description we are given. I'm going to just use a string for demonstration, but you should replace it with something type safe if at all possible.
If this is always on, then just having an instance context (probably a global variable) might be appropriate. When you log in, set the context and forget about it. If it ever isn't set, throw with extreme prejudice. If you can't throw when it isn't set, then it isn't always on.
void setLoggingContext("X:");
If this changes at different levels of abstraction, I would consider a stack based RAII implementation.
LoggingTag tag("X:");
I'm not sure what your requirements are in the scenario when different stack frames pass in different values. I could see where either the top or the bottom of the stack would be reasonable for differing use cases.
void foo() {
LoggingTag tag("X:");
logWarning("foo");
bar();
baz();
}
void bar() {
LoggingTag tag("Y:");
logWarning("bar");
baz();
}
void baz() {
logWarning("baz");
}
Either way this shouldn't affect how you add a message to the log. The baz function doesn't have the context to specify the LoggingTag. It's very important that using logWarning doesn't know about tags for this reason.
If you wanted to tag based on some type, you could do something simple like this.
struct LoggingTag {
LoggingTag(const std::string &tag_) : tag(tag_) {}
template<typename T>
static LoggingTag ByType() {
return LoggingTag(typeid(T).name());
}
std::string tag;
};
void foo() {
LoggingTag tag = LogginTag::ByType<int>();
}
This wouldn't force someone to use typeid(T).name() if they didn't want to, but gave you the convenience.
I like this approach:
class Log {
public:
virtual logString(const std::string&)=0;
};
template <typename T>
Log& operator<<(Log& logger, const T& object) {
std::stringstream converter;
converter << object;
logger.logString(converter.str());
return logger;
}
Simple and quick! All you need to do is reimplement the logString method...
Take a look at zf_log library. It is very small (~2000k lines, ~10KB when compiled) and fast (see comparison table in README.md). It is very close to what you describe as wrapper. It gives you an abstract API that you can use in your project and allows to specify what actual logging implementation to use. See custom_output.c example where syslog is used as output facility. It also could be used privately inside libraries without risk of getting into conflict with other code that could use this library (see ZF_LOG_LIBRARY_PREFIX define for more info).
Even if it's not exactly what you are looking for, I guess it could be a good example for your wrapper thing.