So, I was wondering how to create some kind of a code audit in C++ using a tracking mechanism of sorts.
Consider the following classes, where two separate mirrors, A and B, provide messages to a listener.
class MirrorA
{
void one(int a) { m_mirrrorListener.three(a); }
};
class MirrorB
{
void two(int b) { m_mirrrorListener.three(b); }
};
class MirrorListener
{
void three(int c) { std::cout << c << std::endl; }
};
Now, let's say that, for some reason, three needs to know if it was triggered by one() or two().
We can pass along a value like so:
enum mirrorSource_t
{
FROM_ONE = 1,
FROM_TWO = 2
}
class MirrorA
{
void one(int a) { m_mirrrorListener.three(a, FROM_ONE); }
};
class MirrorB
{
void two(int b) { m_mirrrorListener.three(b, FROM_TWO); }
};
class MirrorListener
{
void three(int c, mirrorSource_t source) { std::cout << c << " From " << source << std::endl; }
};
But then we have to update the signature of three and its invocation whenever it needs new information.
So, what if we had a singleton message tracker (referenced as m_mirrorMessageTracker in other classes) that could track an arbitrary number of messages?
enum mirrorSource_t
{
FROM_ONE = 1,
FROM_TWO = 2
}
class MirrorMessage
{
public:
MirrorMessage(mirrrorSource_t t) : source(t) {}
get() { return source; }
private:
mirrorSource_t source;
};
class MirrorMessageTracker {
public:
MirrorMessage& MirrorMessageTracker::trackEvent(mirrorSource_t value)
{
trackedMessages.push_back(MirrorMessage(value));
return trackedMessages.back();
}
MirrorMessage& MirrorMesssageTracker::getCurrentEvent()
{
return trackedMessages.back();
}
static MirrorMessageTracker& getInstance()
{
if(!m_Tracker)
{
m_pTracker = new MirrorMessageTracker();
}
return *m_pTracker;
}
private:
MirrorMessageTracker() { }; //
static MirrorMessageTracker* m_pTracker;
std::vector<MirrorMessage> trackedMessages; // assumption is that tracked messages are
// single-threaded and unwind in a LIFO manner.
};
class MirrorA
{
void one(int a)
{
MirrorMessage createdMessage = m_MirrorMessageTracker.trackMessage(FROM_ONE);
m_mirrrorListener.three(a);
}
};
class MirrorB
{
void two(int b)
{
MirrorMessage createdMessage = m_MirrorMessageTracker.trackMessage(FROM_TWO);
m_mirrrorListener.three(b);
}
};
class MirrorListener
{
void three(int c)
{
MirrorMessage& message = m_MirrorMessageTracker.getCurrentMessage();
if (message.get() == FROM_ONE)
{
std::cout << c << std::endl;
}
else if (message.get() == FROM_TWO)
{
std::cout << c << c << std::endl;
}
else
{
std::cout << c << c << c << std::endl;
}
}
};
I would like for the tracked message to be removed from the tracker after createdMessage goes out of scope in one and two. Can this be done with a particular type of boost smart pointer? Something like:
std::vector<boost::shared_ptr<MirrorMessage> > trackedMessages;
vector::push_back would create a copy of the message and place it into the vector so I'm not sure if it's possible with a shared pointer, though.
The more common pattern to create singletons actually is
static MirrorMessageTracker& getInstance() {
static MirrorMessageTracker theMirrorMesageTracker;
return theMirrorMesageTracker;
}
Also you should consider to forbid copying and assignment for your MirrorMessageTracker class, by making these operations private:
private:
MirrorMessageTracker() { };
MirrorMessageTracker(const MirrorMessageTracker&); // <<<
MirrorMessageTracker& operator=(const MirrorMessageTracker&); // <<<
Related
A performance bottleneck of my program is frequent calls to functions like following update functions.
Given that flag parameter is always a bool literal, I want to "unroll" the update function to two versions, one with flag=true and one with flag=false, to avoid branch prediction failure.
for normal functions, a bool template parameter can solve this problem easily.
However, template cannot be applied to virtual functions.
I can create two virtual functions manually, but then I have to copy the long code part. It makes futher development harder.
Is there anyway allowing me to write two versions in one function, controlled by a compiling-time constant flag?
#include <iostream>
#include <random>
using std::cout;
using std::endl;
struct Base
{
virtual void update(bool flag) = 0;
};
struct Derived1 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived1 flag=true" << endl;
}
else
{
// some computations
cout << "Derived1 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived1" << endl;
}
};
struct Derived2 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived2 flag=true" << endl;
}
else
{
// some computations
cout << "Derived2 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived2" << endl;
}
};
int main()
{
Base *p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = new Derived1();
}
else
{
p = new Derived2();
}
p->update(false);
p->update(true);
}
Unfortunately, there is no such thing as virtual templates. What can be done however is to create several virtual functions taking an integral (boolean in this particular case) constant, if the flag is really a compile time literal:
#include <iostream>
#include <random>
#include <type_traits>
#include <memory>
using std::cout;
struct Base
{
virtual void updateSeparate(std::true_type) = 0;
virtual void updateSeparate(std::false_type) = 0;
};
struct Derived1 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived1 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived1 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived1\n";
}
};
struct Derived2 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived2 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived2 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived2\n";
}
};
int main()
{
std::unique_ptr<Base> p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = std::make_unique<Derived1>();
}
else
{
p = std::make_unique<Derived2>();
}
p->updateSeparate(std::bool_constant<false>{});
p->updateSeparate(std::bool_constant<true>{});
}
DEMO
However, I cannot tell if that will help or maybe hinder the performance even more by making the vtable lookup time even longer, you have to experiment with that by yourself I'm afraid.
I tried to implement a CRTP pattern with constexpr template parameter, please take a look
template<typename T>
struct Base {
template<bool flag>
int update() {
return static_cast<T*>(this)->template updateImpl<flag>();
}
};
struct Derived1 : public Base<Derived1> {
template<bool flag>
constexpr int updateImpl() {
if constexpr (flag) {
return 1;
} else {
return 2;
}
}
};
struct Derived2 : public Base<Derived2> {
template<bool flag>
constexpr int updateImpl() {
return 3;
}
};
int main() {
auto obj1 = new Derived1();
std::cout << obj1->update<true>(); // 1
std::cout << obj1->update<false>(); // 2
auto obj2 = new Derived2();
std::cout << obj2->update<true>(); // 3
std::cout << obj2->update<false>(); // 3
}
My goal is to separate data from various implementations. I don't want my things to know what actual subclass it is they are working with, either way around. To make things perform only a single task with minimal information.
I'll throw some code in your eyes first.
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <functional>
class Model
{
public:
virtual bool set(int p_attrId, int p_value) {return false;};
virtual bool get(int p_attrId, int & p_value) const {return false;};
};
class Derived: public Model
{
static constexpr int c_classId = 1;
int value = 1;
public:
enum EAttrs
{
eAttr1 = c_classId * 1000
};
virtual bool set(int p_attrId, int p_value) override
{
switch(p_attrId)
{
case eAttr1:
value = p_value;
return true;
default:
return Model::set(p_attrId, p_value);
}
}
virtual bool get(int p_attrId, int & p_value) const override
{
switch(p_attrId)
{
case eAttr1:
p_value = value;
return true;
default:
return Model::get(p_attrId, p_value);
}
}
};
// GuiTextBoxComponent.h
// no includes to any class derived from model
class GuiTextBoxComponent
{
std::weak_ptr<Model> m_model;
int m_attrId;
public:
void draw()
{
auto locked = m_model.lock();
if(locked)
{
int value;
bool result = locked->get(m_attrId, value);
if(!result)
{
std::cout << "Failed to get attribute " << m_attrId << "\n";
return;
}
std::cout << "AttrID: " << m_attrId << " Value: " << value << "\n";
}
else
{
std::cout << "Model is dead\n";
}
}
void setSource(std::weak_ptr<Model> p_model, int p_attrId)
{
m_model = p_model;
m_attrId = p_attrId;
}
};
int main()
{
std::shared_ptr<Model> model (new Derived);
GuiTextBoxComponent textbox;
textbox.setSource(model, Derived::eAttr1);
textbox.draw();
}
The motivation behind this is acquisition of all data from a single interface.
I need to be able to add functionality like the GuiTextBoxComponent, without #include "Derived1.h" in its header.
The challenge with this design is that the Model interface needs to implement all types required from anywhere in the program.
How would you extend the types provided?
Is there some other design that could be used to achieve similar results?
Generally, I think this is an XY problem but here is how you can beautify your code a bit. First, I implemented two interfaces: Getter and Setter like:
enum class EAttrs {
eAttr1
};
template <typename GetterImpl>
struct Getter {
bool get(EAttrs const attrId, int& value) {
switch (attrId) {
case EAttrs::eAttr1:
return static_cast<GetterImpl*>(this)->get(value);
default:
return false;
}
}
};
template <typename SetterImpl>
struct Setter {
bool set(EAttrs const attrId, int value) {
switch (attrId) {
case EAttrs::eAttr1:
return static_cast<SetterImpl*>(this)->set(value);
default:
return false;
}
}
};
Here I used CRTP, i.e. static polymorphism. Then implementation of your derived classes is a bit simpler:
class Derived1 : public Getter<Derived1>, Setter<Derived1> {
int value = 1;
public:
bool set(int p_value) {
value = p_value;
return true;
}
bool get(int & p_value) {
p_value = value;
return true;
}
};
class Derived2 : public Getter<Derived1>, Setter<Derived1> {
int value = 2;
public:
bool set(int p_value) {
value = p_value;
return true;
}
bool get(int & p_value) {
p_value = value;
return true;
}
};
Finally, since we were using CRTP, there is no need for creating std::unique_ptr. Code that's using above classes could look like:
template <typename T>
void printInt(Getter<T>& model, EAttrs p_attrId) {
int value;
bool result = model.get(p_attrId, value);
if (!result)
{
std::cout << "Failed to get attribute " << static_cast<int>(p_attrId) << "\n";
return;
}
std::cout << "AttrID: " << static_cast<int>(p_attrId) << " Value: " << value << "\n";
}
int main()
{
Derived1 derived1;
Derived2 derived2;
printInt(derived1, EAttrs::eAttr1);
printInt(derived2, EAttrs::eAttr1);
}
Check out the DEMO.
P.S. Note the usage of enum class instead of plain enum.
Take a look at this CppCon's talk about Solid principles. Your code might be a good example to apply those principles to.
I am currently working on a small private project using C++ i came up with the following structure:
#include <iostream>
class A
{
std::vector<int> vec;
protected:
virtual bool onAdd(int toAdd) {
// should the 'adding' be suppressed?
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return false;
}
public:
void add(int i) {
if(!onAdd(i)) {
// actual logic
vec.push_back(i);
}
}
};
class B : public A
{
protected:
bool onAdd(int toAdd) override {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
In this example onAdd is basically meant to be a callback for add, but in a more polymorphic way.
The actual problem arises when a class C inherits from B and wants to override onAdd too. In this case the implementation in B will get discarded (i.e. not called) when calling C::add. So basically what I would like to achieve is a constructor-like behaviour where I am able to override the same method in different positions in the class hierarchy and all of those getting called.
My question now is: Is there a possibility/design to achieve this? I am sure that it wouldn't be as easy as cascading constructors, though.
Note: Don't focus too much on the add example. The question is about the callback like structure and not if it makes sense with an add.
I would just call my parents onAdd()
bool C::onAdd(int toAdd) {return my_answer && B::onAdd(toAdd);}
This can be a little confusing if you're expecting other developers to inherit from your base class. But for small private hierarchies it works perfectly.
I sometimes include a using statement to make this more explicit
class C : public B
{
using parent=B;
bool onAdd(int toAdd) override {return my_answer && parent::onAdd(toAdd);}
};
struct RunAndDiscard {
template<class Sig, class...Args>
void operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return;
for (auto* i = start; i != (finish-1); ++i) {
(*i)(args...);
}
(*(finish-1))(std::forward<Args>(args)...);
}
};
template<class Sig, class Combine=RunAndDiscard>
struct invokers {
std::vector<Sig*> targets;
template<class...Args>
decltype(auto) operator()(Args&&...args)const {
return Combine{}( targets.data(), targets.data()+targets.size(), std::forward<Args>(args)... );
}
};
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
This creates a per-instance table of things to do onAdd.
Creating a per-class table is harder; you need to chain your table with your parent type's table, which requires per-class boilerplate.
There is no way to get the C++ compiler to write either the per-instance version, or the per-class version, without doing it yourself.
There are C++20 proposals involving reflection and reification, plus the metaclass proposal, which may involve automating writing code like this (on both a per-instance and per-class basis).
Here is a live example of this technique being tested:
struct AndTogetherResultWithShortCircuit {
template<class Sig, class...Args>
bool operator()(Sig*const* start, Sig*const* finish, Args&&...args)const{
if (start==finish) return true;
for (auto* i = start; i != (finish-1); ++i) {
if (!(*i)(args...)) return false;
}
return (*(finish-1))(std::forward<Args>(args)...);
}
};
class A {
std::vector<int> vec;
protected:
invokers<bool(A*, int), AndTogetherResultWithShortCircuit> onAdd;
public:
void add(int i) {
if (!onAdd(this, i)) {
vec.push_back(i);
}
}
};
class B : public A
{
public:
B() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "B::onAdd(" << x << ")" << std::endl;
return x%2;
});
}
};
class C : public B
{
public:
C() {
onAdd.targets.push_back([](A* self, int x)->bool{
// do some B specific checks
std::cout << "C::onAdd(" << x << ")" << std::endl;
return false;
});
}
};
When you want to write your own OO-system, you can in C++, but C++ doesn't write it for you.
If you want a generic solution perhaps you could use CRTP with variadic templates instead of runtime polymophism.
Taking inspiration from this answer and this answer:
template<class... OnAdders> class A : private OnAdders... {
std::vector<int> vec;
template<class OnAdder>
bool onAdd(int toAdd){
return static_cast<OnAdder*>(this)->onAdd(toAdd);
}
template<typename FirstOnAdder, typename SecondOnAdder, class... RestOnAdders>
bool onAdd(int toAdd){
if (onAdd<FirstOnAdder>(toAdd))
return true;
return onAdd<SecondOnAdder, RestOnAdders...>(toAdd);
}
public:
void add(int i) {
if (onAdd<OnAdders...>(i))
return;
// actual logic
vec.push_back(i);
}
};
class B {
public:
bool onAdd(int toAdd) {
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return false;
}
};
Which you could use like:
A<B,C> a;
a.add(42);
Live demo.
The following solution uses std::function to add each callback during each constructor:
#include <iostream>
#include <vector>
#include <functional>
class A
{
std::vector<int> vec;
protected:
bool onAdd(int toAdd)
{
// do some A specific checks
std::cout << "A::onAdd()" << std::endl;
return true;
}
// vector of callback functions. Initialized with A::onAdd() callback as the first entry
std::vector<std::function<bool(int)>> callbacks{{[this](int toAdd){return onAdd(toAdd); }}};
public:
void add(int i)
{
for(auto& callback : callbacks) {
if(!callback(i))
return;
}
// actual logic
vec.push_back(i);
}
};
class B : public A
{
public:
B()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some B specific checks
std::cout << "B::onAdd()" << std::endl;
return true;
}
};
class C : public B
{
public:
C()
{
callbacks.emplace_back([this](int toAdd){return onAdd(toAdd); });
}
protected:
bool onAdd(int toAdd)
{
// do some C specific checks
std::cout << "C::onAdd()" << std::endl;
// must also call B::onAdd()
return true;
}
};
int main()
{
C c;
c.add(5);
}
Prints:
A::onAdd()
B::onAdd()
C::onAdd()
At the moment I'm dealing with a delightful legacy code class implementing polymorphism by switch-case:
class LegacyClass {
public:
enum InitType {TYPE_A, TYPE_B};
void init(InitType type) {m_type=type;}
int foo() {
if (m_type==TYPE_A)
{
/* ...A-specific work... */
return 1;
}
// else, TYPE_B:
/* ...B-specific work... */
return 2;
}
/** Lots more functions like this **/
private:
InitType m_type;
};
I'd like to refactor this to proper polymorphism, e.g.:
class RefactoredClass {
public:
virtual ~RefactoredClass(){}
virtual int foo()=0;
};
class Class_ImplA : public RefactoredClass {
public:
virtual ~Class_ImplA(){}
int foo() {
/* ...A-specific work... */
return 1;
}
};
class Class_ImplB : public RefactoredClass {
public:
virtual ~Class_ImplB(){}
int foo() {
/* ...B-specific work... */
return 2;
}
};
Unfortunately, I have one crucial problem: due to optimization and architectural considerations, within a primary use of LegacyClass, I cannot use dynamic allocation; the instance is a member of a different class by composition:
class BigImportantClass{
/* ... */
private:
LegacyClass m_legacy;
}
(In this example, BigImportantClass may be dynamically allocated, but the allocation needs to be in one continuous virtual segment, and a single new() call; I can't make further calls to new() in the BigImportantClass ctor or in subsequent initialization methods.)
Is there a good way to initialize a concrete implementation, polymorphically, without using new()?
My own progress so far: What I can do is provide a char[] buffer as a member of BigImportantClass, and somehow initialize a concrete member of RefactoredClass in that memory. The buffer would be large enough to accommodate all implementations of RefactoredClass. However, I do not know how to do this safely. I know the placement-new syntax, but I'm new to dealing with alignment (hence, warned off by the C++-FAQ...), and aligning generically for all concrete implementations of the RefactoredClass interface sounds daunting. Is this the way to go? Or do I have any other options?
Here's some code... just doing the obvious things. I don't use C++11's new union features, which might actually be a more structured way to ensure appropriate alignment and size and clean up the code.
#include <iostream>
template <size_t A, size_t B>
struct max
{
static const size_t value = A > B ? A : B;
};
class X
{
public:
X(char x) { construct(x); }
X(const X& rhs)
{ rhs.interface().copy_construct_at_address(this); }
~X() { interface().~Interface(); }
X& operator=(const X& rhs)
{
// warning - not exception safe
interface().~Interface();
rhs.interface().copy_construct_at_address(this);
return *this;
}
struct Interface
{
virtual ~Interface() { }
virtual void f(int) = 0;
virtual void copy_construct_at_address(void*) const = 0;
};
Interface& interface()
{ return reinterpret_cast<Interface&>(data_); }
const Interface& interface() const
{ return reinterpret_cast<const Interface&>(data_); }
// for convenience use of virtual members...
void f(int x) { interface().f(x); }
private:
void construct(char x)
{
if (x == 'A') new (data_) Impl_A();
else if (x == 'B') new (data_) Impl_B();
}
struct Impl_A : Interface
{
Impl_A() : n_(10) { std::cout << "Impl_A(this " << this << ")\n"; }
~Impl_A() { std::cout << "~Impl_A(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_A::f(x " << x << ") n_ " << n_;
n_ += x / 3;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_A(*this); }
int n_;
};
struct Impl_B : Interface
{
Impl_B() : n_(20) { std::cout << "Impl_B(this " << this << ")\n"; }
~Impl_B() { std::cout << "~Impl_B(this " << this << ")\n"; }
void f(int x)
{ std::cout << "Impl_B::f(x " << x << ") n_ " << n_;
n_ += x / 3.0;
std::cout << " -> " << n_ << '\n'; }
void copy_construct_at_address(void* p) const { new (p) Impl_B(*this); }
double n_;
};
union
{
double align_;
char data_[max<sizeof Impl_A, sizeof Impl_B>::value];
};
};
int main()
{
{
X a('A');
a.f(5);
X b('B');
b.f(5);
X x2(b);
x2.f(6);
x2 = a;
x2.f(7);
}
}
Output (with my comments):
Impl_A(this 0018FF24)
Impl_A::f(x 5) n_ 10 -> 11
Impl_B(this 0018FF04)
Impl_B::f(x 5) n_ 20 -> 21.6667
Impl_B::f(x 6) n_ 21.6667 -> 23.6667
~Impl_B(this 0018FF14) // x2 = a morphs type
Impl_A::f(x 7) n_ 11 -> 13 // x2 value 11 copied per a's above
~Impl_A(this 0018FF14)
~Impl_B(this 0018FF04)
~Impl_A(this 0018FF24)
I implemented this using C++11 unions. This code seems to work under g++ 4.8.2, but it requires the -std=gnu++11 or -std=c++11 flags.
#include <iostream>
class RefactoredClass {
public:
virtual ~RefactoredClass() { }; // Linking error if this is pure. Why?
virtual int foo() = 0;
};
class RefactorA : RefactoredClass {
double data1, data2, data3, data4;
public:
int foo() { return 1; }
~RefactorA() { std::cout << "Destroying RefactorA" << std::endl; }
};
class RefactorB : RefactoredClass {
int data;
public:
int foo () { return 2; }
~RefactorB() { std::cout << "Destroying RefactorB" << std::endl; }
};
// You may need to manually create copy, move, &ct operators for this.
// Requires C++11
union LegacyClass {
RefactorA refA;
RefactorB refB;
LegacyClass(char type) {
switch (type) {
case 'A':
new(this) RefactorA;
break;
case 'B':
new(this) RefactorB;
break;
default:
// Rut-row
break;
}
}
RefactoredClass * AsRefactoredClass() { return (RefactoredClass *)this; }
int foo() { return AsRefactoredClass()->foo(); }
~LegacyClass() { AsRefactoredClass()->~RefactoredClass(); }
};
int main (void) {
LegacyClass A('A');
LegacyClass B('B');
std::cout << A.foo() << std::endl;
std::cout << B.foo() << std::endl;
return 0;
}
Somebody should have made an answer by now...so here's mine.
I'd recommend using a union of char array and one of the biggest integer types:
union {
char refactored_class_buffer[ sizeof RefactoredClass ];
long long refactored_class_buffer_aligner;
};
I also strongly recommend putting an assert or even an if(check) throw; into your factory so that you never, ever, exceed the size of your buffer.
If the data is the same for each case, and you're only changing behaviuor, you don't need to allocate in your core - this is basically a strategy pattern using singleton strategies. You end up using polymorphism in your logic, but not in your data.
class FooStrategy() {
virtual int foo(RefactoredClass& v)=0;
}
class RefactoredClass {
int foo() {
return this.fooStrategy(*this);
}
FooStrategy * fooStrategy;
};
class FooStrategyA : public FooStrategy {
//Use whichever singleton pattern you're happy with.
static FooStrategyA* instance() {
static FooStrategyA fooStrategy;
return &fooStrategy;
}
int foo(RefactoredClass& v) {
//Do something with v's data
}
}
//Same for FooStrategyB
Then when you create a RefactoredClass you set its fooStrategy to FooStrategyA::instance().
I am developing a test-framework. There are a number of test-suites, each is a class with a set of member functions for each individual test.
I would like to find a way to dynamically iterate through all of the tests in a class.
The idealised setup might look something like this:
class A : public Test
{
public:
A() {
addTest(a);
addTest(b);
addTest(c);
}
void a() { cout << "A::a" << endl; }
void b() { cout << "A::b" << endl; }
void c() { cout << "A::c" << endl; }
};
The addTest() method will add its parameter to a list; this list is iterated through at a later point and each method is run.
Is there any way to achieve this? The closest we have come up with so far is this:
class Test
{
public:
template <typename T>
struct UnitTest
{
typedef void (T::*P)();
P f;
UnitTest(P p) : f(p) {}
};
// (this struct simplified: we also include a name and description)
virtual void run(int testId) = 0;
};
class A : public Test
{
public:
A() {
mTests.push_back(UnitTest<A>(&A::a));
mTests.push_back(UnitTest<A>(&A::b));
mTests.push_back(UnitTest<A>(&A::c));
}
void a() { cout << "a" << endl; }
void b() { cout << "b" << endl; }
void c() { cout << "c" << endl; }
// not ideal - this code has to be repeated in every test-suite
void run(int testId)
{
(this->*(mTests[testId].f))();
}
vector<UnitTest<A>> mTests;
};
To invoke one test per-iteration of the main run-loop:
a->run(mTestId++);
This is not ideal because every test-suite (class) has to repeat the run() code and have its own mTests member.
Is there a way to get closer to the ideal?
Make each test a functor or function object. Create a container of pointers to the tests and then iterate over the container:
struct Test_Base_Class
{
virtual bool Execute(void) = 0;
};
typedef std::vector<Test_Base_Class *> Container_Of_Tests;
struct Test_Engine
{
Container_Of_Tests tests_to_run;
void Add_Test(Test_Base_Class * p_new_test)
{
tests_to_run.push_back(p_new_test);
}
void Run_Tests(void)
{
Container_Of_Tests::iterator iter;
for (iter = tests_to_run.begin();
iter != tests_to_run.end();
++iter)
{
(*iter)->Execute(); // Invoke the Execute method on a test.
}
return;
}
}
This is the foundation. I am currently using this pattern but have expanded to include a Resume() method and status reporting.