Between two certain repos I've so far used an interface class (with inheritance), and this I've recently replaced with a callback function using std::function() & std::bind().
Using the old, interface-like method I ended up with this:
//a.hpp
#include "b.hpp"
class A{
public:
A(InterfaceB* pb) : m_pb(pb) {};
void bar(){m_pb->foo();};
private:
InterfaceB* m_pb;
};
--
//b.hpp
#include <iostream>
class InterfaceB{
public:
virtual void foo() = 0;
};
class B : public InterfaceB {
public:
void foo(){ std::cout << "hi"<< std::endl; };
};
--
//main.cpp
#include "a.hpp"
#include <memory>
int main(){
InterfaceB* pb = new B;
A a(pb);
a.bar();
delete pb;
}
--
In UML, I'd draw the little example above like this:
To reduce dependency between the repos (here A and B classes) I'd dropped the interface and used a function wrapper instead.
//a_callback.hpp
#include <functional>
class A{
public:
void setBcallback(std::function<void(void)> callback){m_callback = callback;};
void bar(){m_callback();};
private:
std::function<void(void)> m_callback;
}
--
//b_callback.hpp
#include <iostream>
class B {
public:
void foo(){ std::cout << "hi"<< std::endl; };
}
--
//main.cpp
#include "a_callback.hpp"
#include <functional>
int main(){
A a;
B b;
a.setBcallback(std::bind(&B::foo, &b));
a.bar();
}
--
And this has been the tricky bit for me, I had no luck on Google finding how C++'s std::bind()/std::function() and UML's << bind >> translate to each other. So my question would be, how would one show the use of a function wrapper on a class diagram? Based on what I've found I'd probably go with this:
But it just feels loose and insufficient. Any help would be much appreciated!
This question has been previously marked as a duplicate with this: How to represent Callback in UML Class Diagram . But my question is C++ specific and said 'original' is tagged as Java, unfortunately I got no help from that. My question was not 'how to show a callback in UML' that I think it explains , but more of 'how to show the std::bind() in UML' which I think is trickier. There's two things going on here, one is setting up the function wrapper with bind(), second the call via the wrapper. I just couldn't see how that thread above addresses this specific question. Thank you!
The <<bind>>
dependency refers to UML template binding:
A TemplateBinding is a relationship between a TemplateableElement and a template that specifies the substitutions of actual ParameterableElements for the formal TemplateParameters of the template.
The template binding is a special implementation dependency, that shows that a class is a specialisation of a template, and lays down the template substition.
A typical example would be:
using void_function = std::function<void(void)> ;
In C++ std::bind()
binds parameters to a callable dynamically. This is a completely different semantic.
If you want to show this in UML, it would not be so helpful. You could :
show that the anonymous type that bind returns is a template instantiation of a callable with one argument substituted with a B (very similar diagram to the one above).
if useful, show that this anonymous class depends on B.
if useful, show an optional relation (0..1) from A to this anonymous class, being understood that alternative relations would be possible with other anonymous classes (you could use an OCL constraint if you want to illustrate several on your diagram and make clear that they are mutually exclusive).
Unfortunately, whatever you draw, it will not be as generic and powerful as your C++ design, and it would not help very much to understand.
The goal of an UML diagram is not to program graphically but to guive insights on the internals. So I'd strongly suggest to keep it simple:
the only real relation is between A and an abstract callable class for the callback. That must go on the diagram.
You can also show that this abstract callback can depend on other relevant classes in your diagram. A comment on these dependency relation can explain in simple words that the dependencies express a binding to a member function.