lets say that requirement is this:
As a class user I would like to collect information about a subject and when class has enough information I would like for a class to return to me the list of collected data. Enough information is defined as - when all information from subset of all possible information is collected. That subset is not fixed and it is provided to the class.
For example this is list of all possible information:
{
string name;
int age;
char sex;
string location;
}
and I want to give my users a possibility to tell me to listen from some data source(from which my class parses data) until I get the age and sex.
Problem is that I dont know how to convey that without an enum.
Basically my enum solution is listening to data source until I determine using using std::includes on 2 set of enums(collected, required) that I have collected all the data.
Is it possible to do it without enums?
Whenever I want to decouple the implementation of a piece of logic from where it's needed - in this case the knowledge of "how much data is enough" - I think of a callback function.
Presumably the set of all possible data that your class can collect is known (name, age, sex & location in your example). This means all clients of your class (can) know about it also, without increasing the amount of coupling & dependence.
My solution is to create an "evaluator" class that encapsulates this logic. An instance of a subclass of this class is created by the client and handed to the data collector at the time of the initial request for data; this object is responsible for deciding (and telling the "collector") when enough data has been collected.
#include <string>
// The class that decides when enough data has been collected
// (Provided to class "collector" by its clients)
class evaluator
{
public:
virtual ~evaluator() {};
// Notification callbacks; Returning *this aids in chaining
virtual evaluator& name_collected() { return *this; }
virtual evaluator& age_collected() { return *this; }
virtual evaluator& sex_collected() { return *this; }
virtual evaluator& location_collected() { return *this; }
// Returns true when sufficient data has been collected
virtual bool enough() = 0;
};
// The class that collects all the data
class collector
{
public:
void collect_data( evaluator& e )
{
bool enough = false;
while ( !enough )
{
// Listen to data source...
// When data comes in...
if ( /* data is name */ )
{
name = /* store data */
enough = e.name_collected().enough();
}
else if ( /* data is age */ )
{
age = /* store data */
enough = e.age_collected().enough();
}
/* etc. */
}
}
// Data to collect
std::string name;
int age;
char sex;
std::string location;
};
In your example, you wanted a particular client to be able to specify that the combination of age and sex is sufficient. So you subclass evaluator like so:
class age_and_sex_required : public evaluator
{
public:
age_and_sex_required()
: got_age( false )
, got_sex( false )
{
}
virtual age_and_sex_required& age_collected() override
{
got_age = true;
return *this;
}
virtual age_and_sex_required& sex_collected() override
{
got_sex = true;
return *this;
}
virtual bool enough() override
{
return got_age && got_sex;
}
private:
bool got_age;
bool got_sex;
};
The client passes an instance of this class when requesting data:
collector c;
c.collect_data( age_and_sex_required() );
The collect_data method quits and returns when the age_and_sex_required instance reports that the amount of data collected is "enough", and you haven't built any logic, knowledge, enums, whatever, into the collector class. Also, the logic of what constitutes "enough" is infinitely configurable with no further changes to the collector class.
----- EDIT -----
An alternate version would not use a class with the ..._collected() methods but simply a single (typedef'd) function that accepts the collector as a parameter and returns boolean:
#include <functional>
typedef std::function< bool( collector const& ) > evaluator_t;
The code in collector::collect_data(...) would simply call
enough = e( *this );
each time a piece of data is collected.
This would eliminate the necessity of the separate evaluator abstract interface, but would add dependence on the collector class itself, as the object passed as the evaluator_t function would be responsible for checking the state of the collector object to evaluate whether enough data has been collected (and would require the collector to have sufficient public interface to inquire about its state):
bool age_and_sex_required( collector const& c )
{
// Assuming "age" and "sex" are initialized to -1 and 'X' to indicate "empty"
// (This could be improved by changing the members of "collector" to use
// boost::optional<int>, boost::optional<char>, etc.)
return (c.age >= 0) && (c.sex != 'X');
}
Not sure if this will work for you or not, but because each item may or may not be present, boost::optional sprung to mind.
{
boost::optional<string> name;
boost::optional<int> age;
boost::optional<char> sex;
boost::optional<string> location;
}
Your class could then have a bool validate() method which checks the presence of the required set of items. This could either be a class method, or passed in as a callback.
You can define a value by default for each member saying "i'm required".
static const string required_name = /* your default name */;
// ...
You can also use an integer as a bitmask which will behave like a set of enums.
typedef int mask_type;
static const mask_type name_flag = 0x01;
static const mask_type age_flag = 0x02;
static const mask_type sex_flag = 0x04;
static const mask_type location_flag = 0x08;
//...
mask_type required = name_flag | age_flag; // need to collect name & age
collect(&my_instance, required) // collect and set required values
Easy to use and no overhead than a single int :
value is not required anymore : required &= ~xx_flag
no more values required : bool(required)
value is required : bool(required & xx_flag)
...
Enums seems the cleanest way to do this, but I suppose if you preferred you could use short strings with a different character corresponding to each type of data. That's not so clean but might be easier to debug.
Couldnt you accomplish such behaviour by using a template and a abstract class, doing something like this?
class SomeAbstract
{
public:
virtual bool getRequired() = 0;
virtual void setRequired(bool req) = 0;
};
template <class T>
class SomeTemplate
{
T value;
bool required;
public:
TemplateName(T t)
{
value = t;
required = false;
}
void setRequired(bool req)
{
required = req;
}
bool getRequired()
{
return required;
}
void setValue(T newValue)
{
value = newValue;
}
T getValue()
{
return value;
}
};
you can then declare your list of attributes as the same type.
SomeTemplate<string> name;
SomeTemplate<int> age;
SomeTemplate<char> sex;
SomeTemplate<string> location;
Since the template is inheriting the same type you can store them in a std::vector<SomeAbstract> and treat them all the same.
This is not tested code and the idea may have some improvements but i hope you get my point.
Related
Plz check following c++ code: (nothing special, should be compliant to c++ 2nd edition from 1991)
class C
{
// also defines all the methods called in template method below with the obvious name and args.
public: template<typename TEnum> void SetNullableEnumValuePtr(CNullable<TEnum>* aEnumPtr)
{
if(sizeof(TEnum) == 4)
{
this->SetNullableUInt32Ptr(reinterpret_cast<CNullable<UInt32>*>(aEnumPtr));
}
else if (sizeof(TEnum) == 2)
{
this->SetNullableUInt16Ptr(reinterpret_cast<CNullable<UInt16>*>(aEnumPtr));
}
else if (sizeof(TEnum) == 1)
{
this->SetNullableUInt8Ptr(reinterpret_cast<CNullable<UInt8>*>(aEnumPtr));
}
else
{
this->FailEnumSize();
}
}
}
basic conditions
class CNullable follows the well known, basic nullable pattern implemented i.e. for c# in certain frameworks but could also be any template with one argument.
as the names imply, TEnum is used for different enum types. i.e. enum FooEnum { foo };
For different platforms/compilers it is true, that with for the same enum type it goes to different if branches: On Win32 all enums are compiled with a size of 4 bytes always. On my MCU it compiles to uint8, if the values of the enum field implies to do so.
1. Not my focus:
i'm not sure, if the c++ standard allows compliant compilers to generate enums with different sizes in respect of the required size but i think it is said, that it is compliant.
2. not my focus:
it is also obvious that a cleaner / more robust solution would generate explicit template instances for the function for ALL used enum types. however i might do this and hope the compiler/optimizer is smart/compliant enough not to generate extra code for all types.
3. Not my focus:
i know that reinterpret_cast can be evil but there is a reason the c++ standard defines it. so please stop downrating my questions just because you dont like it or dont understand it.
4. Not my focus:
i know there are certain websites, you can test code on different compilers.
5. would help too:
also if you have a better idea how to treat this coding issue you're welcome.
6. My focus:
i wanna focus this question on the issue, if the c++ standard [1] (or any other standard) defines rule(s), that the templates instances for intXX and uintXX (Where XX is the bit width and u indicates a unsigned version of the native integer) must forcefully compile to a code where a reinterpret_cast from CNullable<unsigned intXX> to CNullable<intXX> is guaranteed to run properly. it seems to be likely that a straight forward implementation of the tool chain may not cause problems in this case, but i got used to be carefull with such assumptions.
conclusion:
if one could give me the reference(s) to chapter inside the (c++) or other standard treading these issues (1 to 6) - that would be great.
thank you!
[1] Please understand the sad reality, that the platform i work on does even not have a ready compiler specification. so it is quite trial and error and i wanna understand the techniques behind to get a better feeling for it - because treading the issue deterministic seems not to be possible since the compiler reference does not give a clear statement what standard it supports: They stated an ETSI standard rather than an iso c++ standard and they didnt give enough info to find the documentation of the standard - no version number, no document number, no document name. when i search for the info given in the compiler documentation on the ETSI page i get > 24.000 results (!) XD
PS: Edit: I request the info:
a) Which standards / specifications ensure that this code runs properly?
b) Does anyone have a clean solution for an abstraction using different template instances for different enum types?
Ok think i i have a clean solution. It uses a wrapper pattern to hide the abstraction of concrete value types behind a virtual method.
I hope that is enough code to get the intention. I also put a very simple example of how i use it.
I guess in newer c++ version there are some stl elements which can replace the classes i wrote. But i need it for a very old c++ standard, which even isn't iso.
I really hope there are no errors since not all symbols are defined. but the essential stuff shall be shown in this example implementation.
// platform dependent UInt32 type.
typedef unsigned __int32 UInt32;
template<typename T>
class CNullable
{
public: bool HasValue;
public: T Value;
public: CNullable(): Value(), HasValue(false) {}
public: CNullable(const T& aValue): Value(aValue), HasValue(true) {}
public: template<typename T1>
CNullable<T1> To() const
{
return this->HasValue ? CNullable<T1>(static_cast<T1>(this->Value)) : CNullable<T1>();
}
CNullable<UInt32> ToU32n() const
{
return this->To<UInt32>();
}
};
// U32-Nullable type
typedef CNullable<UInt32> UInt32n;
// U32-Nullable argument type.
typedef const CNullable<UInt32>& UInt32na;
// Some kind of variant value that can store different types of values pointing into an (intended) statically allocated model
class CValue
{
// Report failure. Break debuger, raise exception, log error - whatever.
private: static void Fail(const char* aTextPtr);
// Sets the value in the (intended) statically allocated datamodel
// Simple example with a UInt32 as new value
public: void SetTargetValue(UInt32na rhs);
// Sets the value in the (intended) statically allocated datamodel
// May use a visitor pattern (GOF) for resolving assigned types, but thats not the topic here.
public: void SetTargetValue(const CValue& rhs);
// Ensures that object is not sealed an fails if so.
private: bool CheckNotSealed();
// Allows to change to sealed state to protect the object agains modification.
// protection for "as static as possible"-memory-design
public: void Seal();
// Base class for Wrappers
class CValueWrapper
{
public: virtual ~CValueWrapper() {}
// Converts the current value as an U32.
public: virtual UInt32n GetInterpretedU32n() { Fail("Data conversion not supported."); return UInt32n(); }
// converts the new value from an U32 and sets the value
public: virtual void SetInterpretedU32n(UInt32na aU32n) { Fail("Data conversion not supported."); }
};
// Wrappers Base class for any enum related type.
class CEnumWrapperBase : public CValueWrapper
{
public: virtual UInt32n GetU32n() const = 0;
public: virtual void SetU32n(UInt32na aU32n) const = 0;
public: virtual UInt32n GetInterpretedU32n() { return this->GetU32n(); }
public: virtual void SetInterpretedU32n(UInt32na aU32n) { this->SetU32n(aU32n); }
};
// Wrapper base class for values of type = Nullable<TEnums>
template<class TEnum> class CNullableEnumWrapper : public CEnumWrapperBase
{
private: CNullable<TEnum>* mNullableEnumPtr;
public: CNullableEnumWrapper(CNullable<TEnum>* aNullableEnumPtr)
:
mNullableEnumPtr(aNullableEnumPtr)
{
}
public: virtual UInt32n GetU32n() const
{
return this->mNullableEnumPtr ? this->mNullableEnumPtr->ToU32n() : UInt32n();
}
public: virtual void SetU32n(UInt32na aU32n) const
{
if (this->mNullableEnumPtr)
{
*this->mNullableEnumPtr = aU32n.To<TEnum>();
}
}
};
// Wrapper base class for values of type = Nullable<TEnums>
template<class TEnum> class CEnumWrapper : public CEnumWrapperBase
{
public: CEnumWrapper(TEnum* aEnumPtr)
:
mEnumPtr(aEnumPtr)
{
}
private: TEnum* mEnumPtr;
public: virtual UInt32n GetU32n() const
{
return this->mEnumPtr ? static_cast<UInt32>(*this->mEnumPtr) : UInt32n();
}
public: virtual void SetU32n(UInt32na aU32n) const
{
if (this->mEnumPtr
&& aU32n.HasValue)
{
*this->mEnumPtr = static_cast<TEnum>(aU32n.Value);
}
}
};
// Allows to lock instantian of wrapper objects.
// In my bare metal application all wrappers are created on application startup
// and stay allocated until the device is switched of (by disconnecting power)
// [ThreadStatic]
public: static bool InstanciateValueWrapperEnabled;
// Set pointer to enum value (intended to be allocated in a static model)
public: template<class TEnum> void SetEnumValuePtr(TEnum* aEnumPtr)
{
if (this->InstanciateValueWrapperEnabled)
{
if (this->CheckNotSealed())
{
this->SetValueWrapperPtr(new CEnumWrapper<TEnum>(aEnumPtr), true);
}
}
else
{
Fail("Invalid operation.");
}
}
// Set pointer to nullable<enum> value (intended to be allocated in a static model)
public: template<class TEnum> void SetNullableEnumValuePtr(CNullable<TEnum>* aEnumPtr)
{
if (this->InstanciateValueWrapperEnabled)
{
if (this->CheckNotSealed())
{
this->SetValueWrapperPtr(new CNullableEnumWrapper<TEnum>(aEnumPtr), true);
}
}
else
{
Fail("Invalid operation.");
}
}
// Sets the member var and data type to 'CValueWrapper' (may support some types natively without a wrapper object)
public: void SetValueWrapperPtr(CValueWrapper* aValueWrapperPtr, bool aOwning);
};
// Model Base Code
//////////////////////////////////////
/// Application specific code
enum FooEnum { FooEnum_Val1 };
// Reads data from StdIn, uart, or whatever.
UInt32 ReadU32();
// Process data, for example output calculated data to another hardware interface.
void Process(CValue** aValuePtrs);
// Simple example of how its being used.
// in real environment its likely to encapsulate a set of CValue objects
// in a ModelInstance-Object and build it by a ModelDefinition object parsing a model definiton language (mdl)
// or adapt generated code. etc. etc...
void main()
{
// Define the static model:
static FooEnum gFooEnum;
static CNullable<FooEnum> gNullableFooEnum;
// Define the values to access the static model
CValue aFooEnumVal;
CValue aNullableFooEnumVal;
// Begin of init:
CValue::InstanciateValueWrapperEnabled = true;
aFooEnumVal.SetEnumValuePtr(&gFooEnum);
aNullableFooEnumVal.SetNullableEnumValuePtr(&gNullableFooEnum);
CValue::InstanciateValueWrapperEnabled = false;
// End of init
// Create an array of values
const UInt32 aPropertyCount = 2;
CValue* aPropertyPtrs[aPropertyCount] =
{
&aFooEnumVal,
&aNullableFooEnumVal
};
for (UInt32 aIdx = 0; aIdx < aPropertyCount; ++aIdx)
{
aPropertyPtrs[aIdx]->Seal();
}
// Very simple and unsave data receiption loop.
while (true)
{
UInt32 aPropertyIdToSet = ReadU32(); // The property id to receive.
UInt32 aNewValHasValue = ReadU32(); // Wether the value is defined
UInt32 aNewValValue = ReadU32(); // The value
UInt32n aNewVal // Nullable for NewValue
= aNewValHasValue // if value is defined
? UInt32n(aNewValValue) // Create a nullable which has a value
: UInt32n() // Create a nullable which has no value
;
CValue* aValuePtr = aPropertyPtrs[aPropertyIdToSet]; // Get the value to receive.
aValuePtr->SetTargetValue(aNewVal); // Set the value to the static model
Process(aPropertyPtrs); // Process data newly received.
}
}
I have a use case that involves collections of sensor objects that return a bool (indicating the state of the sensor). In some cases the collection object is interested in the inverse of a the sensor value, but I want to use the same interface for both cases so that the collection doesn't need to track this. An example might be
Result = sensorA | not(sensorB)
where the the value of sensorA and not(sensorB) are accessed using the same interface. I've come up with a couple of solutions for this, none of which seem as simple as I originally expected the problem to be.
Firstly, I can realize the goal by creating another class that inherits from the same base interface and performs the translation. However this seems a little clunky as I have to instantiate a inverting object for each sensor:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class ObservedSensorBase
{
public:
virtual bool getState(void) = 0;
protected:
ObservedSensorBase() { inverted = new InvertSensor(this); }
};
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state) {}
bool getState(void) { return mState; }
private:
bool mState;
};
class InvertSensor : public ObservedSensorBase
{
public:
InvertSensor(ObservedSensorBase *sensor) :mSensor(sensor) {}
bool getState(void) { return !mSensor->getState(); }
private:
ObservedSensorBase *mSensor;
};
int main()
{
ConcreteSensor sensorA(true);
InvertSensor notSensorA(&sensorA);
vector <class ObservedSensorBas*> sensors;
sensors.push_back(&sensorA);
sensors.push_back(¬SensorA);
for (class ObservedSensorBase* it : sensors)
{
cout << it->getState() << endl;
}
return 0;
}
Prints:
1
0
Ideally I'm looking for the original concrete sensor class to be able to return the inverted functionality. I can do this if I add a public class to each concrete sensor:
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state),inv(this) {}
bool getState(void) { return mState; }
class InvertSensor inv;
private:
bool mState;
};
...
sensors.push_back(&sensorA.inv);
Prints
0
but this seems a little cumbersome, as its a new variable in each concrete class. I can't add it to the base class, as InvertSensor inherits from the base, so InvertSensor isn't fully defined and can't be instantiated (at least I haven't been able to do so).
The other approach I've investigated is using an object factory:
ObservedSensorBase *invertFactory(ObservedSensorBase *sensor)
{
static map<ObservedSensorBase *, ObservedSensorBase *> m;
// Create an instance of the inverter for this object if it doesn't already exist
if (m.find(sensor) == m.end())
{
m[sensor] = new InvertSensor(sensor);
}
// Provide the inverting object for the passed sensor
return m[sensor];
}
...
sensors.push_back(invertFactory(&sensorA));
Prints
0
Is there another solution that I'm missing? Ideally something inherent in the class that each concrete instance can inherit from, but at this point it's become a bit of an intellectual challenge as well :)
--- EDIT ---
Thanks for the comments so far.
To clarify the objective better, this is for a little project for an Arduino to control signals on a model railroad. For the purposes here, assume that the signals can only show green and red. They show red when any track occupancy circuit or switch orientation that the signal is 'protecting' against indicates its unsafe for a train to proceed (and green otherwise).
Both the track detection and switch orientation objects would be concrete instances of the base sensor, but it's the switch orientation that creates this use case. If we have two signals, each of which is 'protecting' the two approaches to the two-track end of a single switch, one signal will want to use the switch orientation sensor 'as-is', and the other will want to use the inverted sensor value (to represent which way the switch is thrown).
I'm wanting to be able to invert the sensors' state representation when loading the into the signal object that holds them to avoid having to store a separate 'invert this signal' indication in the signal object, or manually instantiate a separate object that performs the inversion.
So something like
Signal1 protects SensorA (trackA) and Switch B
Signal2 protects SensorC (trackC) and not(SwitchB)
Here is an example of the signal (a container of sensors that just ORs them all together) e.g.
class Signal
{
public:
void protect(class ObservedSensorBase *sensor) { mSensors.push_back(sensor); }
void periodicLoop(void)
{
bool anyProtectedSensorActive = false;
for ( auto it = mSensors.begin();
it != mSensors.end() && !anyProtectedSensorActive;
++it)
{ anyProtectedSensorActive |= (*it)->getState(); }
if(anyProtectedSensorActive)
{ /* set Signal Red */ }
else
{ /* set signal Green */ }
}
private:
vector <class ObservedSensorBase*> mSensors; // protected sensors
};
...
Signal signal1;
Signal signal2;
signal1.protect(&sensorA);
signal1.protect(&sensorB);
signal1.protect(&sensorC);
signal1.protect(¬SensorB);
However, after playing with #Jason C's recommendation to put something in the base class (which I couldn't get working prior to asking the question, or after his suggestion) it occured to me that I could create
// Invert Sensor and ObservedSensorBase are declared as above...
class InvertedSensorBase : public ObservedSensorBase
{
public:
InvertedSensorBase() : inverted(this) {}
class InvertSensor inverted;
};
// Change the inheritance of the concrete observer
//class ConcreteSensor : public ObservedSensorBase
class ConcreteSensor : public InvertedSensorBase
And now SensorA.inverted seems to fit the bill very well.
Of course, since this is mostly a side project to return to C++ and learn C++11 after a long absence, if anyone has alternate suggestions about any point, I'd be more than happy to see them.
If you want a really no-effort solution you could store pair<ObservedSensorBase*,bool>'s in your container, where the boolean is whether you want to invert or not, and just have your logic invert the value based on that bool:
typedef pair<ObservedSensorBase *,bool> SensorWithFlag; // ...or something
vector<SensorWithFlag> sensors;
sensors.push_back(SensorWithFlag(sensor1, true)); // invert
sensors.push_back(SensorWithFlag(sensor2, false)); // don't invert
// then later when you use it, say 'n' is an index:
bool state = (sensors[n].first->getState() != sensors[n].second);
But if not, I suppose you could do the inversion in the base:
class ObservedSensorBase {
...
public:
void setInvertState (bool invertState) {
invertState_ = invertState;
}
bool getState () {
return invertState_ != getState_(); // != is xor
}
protected:
virtual bool getState_ () = 0;
private:
bool invertState_;
};
Then all subclasses implement getState_ instead of getState, and all have the ability to have their results inverted by setting setInvertState(true).
But this seems weird. Perhaps you could add some more details about how your containers are using these values. I feel like there may be a better way in general to structure your program and algorithms.
Another option is to use your "inverting filter" option but manage it in the base:
class ObservedSensorBase {
...
public:
ObservedSensorBase (...) : inv_(this) { ... }
InvertSensor * inverted () { return &inv_; }
private:
InvertSensor inv_;
};
Then you can just add mySensor->inverted() to your container when needed. This has the following caveats:
Do not call any virtual methods of ObservedSensorBase from InvertSensor's constructor.
Do not call any methods of InvertSensor that may lead to virtual base methods being called, from ObservedSensorBase's constructor.
Pointer returned by inverted() is invalidated when sensor is deleted.
The first two points are important because this won't be fully constructed yet when constructing subclasses.
This way, every sensor automatically has an inverted version of itself that comes along with it, and you don't have to manage them manually.
Yet another solution is to create wrappers around sensor objects, but keep them simple and store them directly in containers instead of storing pointers to them, to keep memory management easier. For example:
class SensorValue {
public:
SensorValue (ObservedSensorBase *s, bool invert)
: s_(s), i_(invert) { }
bool getState () { return i_ != s_->getState(); }
ObservedSensorBase * sensor () { return s_; }
private:
ObservedSensorBase *s_;
bool i_;
};
// then later, let's say you have some sensors:
ObservedSensorBase *sensor1 = ...;
ObservedSensorBase *sensor2 = ...;
// you can have containers like this:
vector<SensorValue> collection1, collection2;
// and you can use normal/inverted states as needed:
collection1.push_back(SensorValue(sensor1, false)); // normal values
collection1.push_back(SensorValue(sensor2, false));
collection2.push_back(SensorValue(sensor1, true)); // and inverted
collection2.push_back(SensorValue(sensor2, true)); // at the same time
// if you ever need the sensor object itself you can use SensorValue#sensor:
for (vector<SensorValue>::iterator i = collection1.begin();
i != collection1.end(); ++ i)
{
bool state = i->getState(); // normal or inverted, transparent to us here
ObservedSensorBase *sensor = i->sensor(); // can be used for whatever.
// note that i->getState() != i->sensor()->getState() if we're
// using an inverted SensorValue.
}
// and they aren't pointers, you can just do this with no leaks:
collection1.clear();
collection2.clear();
// although of course you still do this for sensor cleanup:
delete sensor2;
delete sensor1;
This is sort of conceptually like your inverted sensor object approach except SensorValue isn't an ObservedSensorBase, it's lightweight and cheaply copyable, and you can just store them directly in containers instead of passing around pointers.
It's very similar to storing e.g. pair<ObservedSensorBase*,bool> (where you store sensor and invert flag) in your containers instead, except unlike pair it gives you a convenient getState() member, and has some semantic meaning.
I am trying to figure out the best way to design my program features.
A major component of the program is a Camera class. This Camera object represents the program user interface to a real camera, which interfaces to a computer through a frame grabber card. The camera class can link to a frame grabber, start and stop acquisition, and also mutate/access many different camera properties. When I say many, I'm talking about over 250 unique commands. Each unique command is issued to the camera by sending a serial string through the framegrabber to the physical camera. Each command can be thought of as one of three types. An action, a query, and a value.
An action command is something that doesn't require an equals sign, for example "reset", "open", "close"
A query is something that you can get, but not set, that is usually associated with a value. For example "temperature=?", "sernum=?", "maxframerate=?" commands would cause the camera to send back information. These values cannot be mutated so "temperature=20" would result in an error.
A value is something you can get and set that is usually associated with a value. For example "framerate=30" and "framerate=?" are two unique commands, but I consider the base string "framerate" to be a value command type because it can be both mutated and accessed.
The 250 unique commands can be reduced to ~100 CameraActions, CameraQuerys, and CameraValues. Instead of having 250 methods in my Camera class, I had an idea to compose command objects instead of individual setters, getters, and actions. The command string can be provided in the constructor, or reset with a setter. Then I could compose a CameraCommands object that holds all of the available commands, and provide that as a public member to my Camera.
//CameraAction.h =============================================
class CameraAction {
public:
CameraAction(std::string commandString, SerialInterface* serialInterface);
void operator()() { _serialInterface->sendString(_commandString); }
private:
SerialInterface* _serialInterface;
std::string _commandString;
};
//CameraValue.h =====================================================
class CameraValue {
public:
CameraValue(std::string commandString, double min, double max, SerialInterface* serialInterface);
void set(double value)
{
if(value > _maxValue) { throw std::runtime_error("value too high"); }
if(value < _minValue) { throw std::runtime_error("value too low"); }
std::string valueString = std::to_string(value);
_serialInterface->sendString(_commandString + "=" + valueString);
}
double get()
{
std::string valueString = _serialInterface->sendString(_commandString + "=?");
return atof(valueString.c_str());
}
private:
SerialInterface* _serialInterface;
std::string _commandString;
double _minValue;
double _maxValue;
};
//CameraCommands.h ===================================================
class CameraCommands {
public:
CameraCommands();
CameraAction reset;
CameraQuery temperature;
CameraValue framerate;
CameraValue sensitivity;
//... >100 more of these guys
};
//Camera.h ===========================================================
class Camera {
public:
Camera();
CameraCommands cmd;
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
so that the user could do something like:
Camera myCamera;
myCamera.cmd.reset();
myCamera.cmd.framerate.set(30);
myCamera.cmd.sensitivity.set(95);
double temperature = myCamera.cmd.temperature.get();
myCamera.startAcquisition();
etc...
The main problem here is that I'm exposing public member variables, which is supposed to be a massive no-no. Is my current object design logical, or should I simply implement 250 setters and getters and 100 more setters and getters to mutate the minimum and maximum settable values.
This seems kludgey to me because there are also many setters/getters associated with the Camera object that are unrelated to the user commands. It's nice for the user interface to provide the scope of the method (cmd) for the user to know whether something is being mutated physically in the camera, or just being mutated in the programmatic object (other methods). Is there any better way to design my program?
You've basically described an interesting hierarchy:
Command -> Query -> Value.
A Command holds the string that is the text of the command;
It can also offer a protected Send() method for its children to call.
A Query also holds a (protected) int variable (or whatever) that you can get() and/or operator int() immediately, or query() from the camera;
A Value adds the set() and/or operator =(int) command to Query.
The constructor (in particular) of Value can have min and max as you describe.
The Camera object can then have a number of public members:
class Camera {
private: // Classes that no-one else can have!
class Command; friend Command;
#include "Camera.Command.inc"
class Query; friend Query;
#include "Camera.Query.inc"
class Value; friend Value;
#include "Camera.Value.inc"
public: // Variables using above classes
Command reset;
Command open; // Maybe make this one private, for friends?
Command close; // Ditto?
Query temperature;
Query sernum;
Query maxFrameRate;
Value frameRate;
private: // Variables
SerialPort port; // Allow Command and co. access to this
}; // Camera
By organising it like this, then:
The user of the variables can't make impossible requests - there is no method to do so;
The query() and set() methods hide the mechanism to interface with the physical camera.
You'll note I've added #include "Camera.XXX.inc" in the middle of the Camera class. Note:
It doesn't clutter the Camera class with the definitions of those sub-Classes - but the C++ compiler needs them before you can use them, so you need to have them there. And if you want to know what they do, just open the file!
I gave them the .inc extension since they're "included" in the .h file: they don't stand alone as their own header file.
You can use one or more structs to group "settings", and then expose a method to set them:
typedef struct settings{
int setting1;
int setting2;
}MySettings;
class Myclass{
private :
int setting1;
int setting2;
public Myclass(MySettigs *settings)
{
if(null != settings){
setting1=settings->setting1;
setting2=settings->setting2;
}
}
public void ChangeSettings (MySettings *setting){
if(null != settings)
{
setting1=settings->setting1;
setting2=settings->setting2;
}
}
public void TakeSettings (MySettigs *settings){
[copy local variables into the passed struct]
}
I strongly advise to be careful when changing settings while the object is "operational".You can fall in an undefined state where settings are being changed while another thread is using them.
In your mentioned design I don't think exposing public members through composition is a big no-no.
When exposing public members, the big no-no is unsafe access to your class internals.
An example would be allowing public access to CameraValue::_maxValue. A user could change that value to anything, causing all sorts of undefined behaviour.
Were it up to me to design this I wouldn't have a CameraCommands member, as from the looks of it it doesn't add anything other then a level of indirection.
I would either add all the CameraAction and CameraValue members as part of the camera class, or inherit them.
Something like this:
Merging CameraCommands into Camera:
class Camera
{
public:
Camera();
CameraAction reset;
CameraQuery temperature;
CameraValue framerate;
CameraValue sensitivity;
//... >100 more of these guys
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
Inheriting CameraCommands into Camera:
class Camera : public CameraCommands
{
public:
Camera();
void startAcquisition();
void stopAcquisition();
void setDataBuffer(void* buffer);
void setOtherThing(int thing);
};
You can even provide some operators for CameraValue etc so that you can set a value through assignment (operator=), and get a value through either implicit conversion (operator T) or dereferencing (operator*):
template<typename T>
class CameraValue
{
public
CameraValue(SerialInterface*, std::string cmd);
CameraValue& operator=(const T& val)
{
_val = val;
std::string val_str = std::to_string(_val);
_ser_ifc->sendString(_cmd + "=" + val_str);
}
const T& get() const
{
return _val;
}
// implicit access to _val
operator const T&() const
{
return _val;
}
// dereference operator to access _val
const T& operator*() const
{
return _val;
}
private:
T _val;
SerialInterface* _ser_ifc;
std::string _cmd;
};
Then use CameraValue in your class as follows:
using CameraFramerate = CameraValue<int>;
CameraFramerate framerate;
The above techniques offer (IMO) a more composable use of Camera, such as the following:
Camera camera;
// setting values
camera.framerate = 30;
camera.sensitivity = 95;
// getting values
int framerate = camera.framerate; // uses operator T&()
int framerate = *camera.framerate; // uses operator*()
The key point here is that Camera::framerate etc don't allow any access that could change your camera class' internal state in an undefined and/or unsafe manner.
If for example I have a builder set up so I can create objects like so:
Node node = NodeBuilder()
.withName(someName)
.withDescription(someDesc)
.withData(someData)
.build();
How can I make sure that all variables used to build the object have been set before the build method?
Eg:
Node node = NodeBuilder()
.withName(someName)
.build();
Isn't a useful node because the description and data haven't been set.
The reason I'm using the builder pattern is because without it, I'd need a lot of combination of constructors. For example the name and description can be set by taking a Field object, and the data can be set using a filename:
Node node = NodeBuilder()
.withField(someField) //Sets name and description
.withData(someData) //or withFile(filename)
.build(); //can be built as all variables are set
Otherwise 4 constructors would be needed (Field, Data), (Field, Filename), (Name, Description, Data), (Name, Description, Filename). Which gets much worse when more parameters are needed.
The reason for these "convenience" methods, is because multiple nodes have to be built, so it saves a lot of repeated lines like:
Node(modelField.name, modelField.description, Data(modelFile)),
Node(dateField.name, dateField.description, Data(dateFile)),
//etc
But there are some cases when a node needs to be built with data that isn't from a file, and/or the name and description are not based on a field. Also there may be multiple nodes that share the same values, so instead of:
Node(modelField, modelFilename, AlignLeft),
Node(dateField, someData, AlignLeft),
//Node(..., AlignLeft) etc
You can have:
LeftNode = NodeBuilder().with(AlignLeft);
LeftNode.withField(modelField).withFile(modelFilename).build(),
LeftNode.withField(dateField).withData(someData).build()
So I think my needs match the builder pattern pretty well, except for the ability to build incomplete objects. The normal recommendation of "put required parameters in the constructor and have the builder methods for the optional parameters" doesn't apply here for the reasons above.
The actual question: How can I make sure all the parameters have been set before build is called at compile time? I'm using C++11.
(At runtime I can just set a flag bits for each parameter and assert that all the flags are set in build)
Alternatively is there some other pattern to deal with a large number of combinations of constructors?
Disclaimer: This is just a quick shot, but I hope it gets you an idea of what you need.
If you want this to be a compiler time error, the compiler needs to know about the currently set parameters at every stage of the construction. You can achieve this by having a distinct type for every combination of currently set parameters.
template <unsigned CurrentSet>
class NodeBuilderTemplate
This makes the set parameters a part of the NodeBuilder type; CurrentSet is used as a bit field. Now you need a bit for every available parameter:
enum
{
Description = (1 << 0),
Name = (1 << 1),
Value = (1 << 2)
};
You start with a NodeBuilder that has no parameters set:
typedef NodeBuilderTemplate<0> NodeBuilder;
And every setter has to return a new NodeBuilder with the respective bit added to the bitfield:
NodeBuilderTemplate<CurrentSet | BuildBits::Description> withDescription(std::string description)
{
NodeBuilderTemplate nextBuilder = *this;
nextBuilder.m_description = std::move(description);
return nextBuilder;
}
Now you can use a static_assert in your build function to make sure CurrentSet shows a valid combination of set parameters:
Node build()
{
static_assert(
((CurrentSet & (BuildBits::Description | BuildBits::Name)) == (BuildBits::Description | BuildBits::Name)) ||
(CurrentSet & BuildBits::Value),
"build is not allowed yet"
);
// build a node
}
This will trigger a compile time error whenever someone tries to call build() on a NodeBuilder that is missing some parameters.
Running example: http://coliru.stacked-crooked.com/a/8ea8eeb7c359afc5
I ended up using templates to return different types and only have the build method on the final type. However it does make copies every time you set a parameter:
(using the code from Horstling, but modified to how I did it)
template<int flags = 0>
class NodeBuilder {
template<int anyflags>
friend class NodeBuilder;
enum Flags {
Description,
Name,
Value,
TotalFlags
};
public:
template<int anyflags>
NodeBuilder(const NodeBuilder<anyflags>& cpy) : m_buildingNode(cpy.m_buildingNode) {};
template<int pos>
using NextBuilder = NodeBuilder<flags | (1 << pos)>;
//The && at the end is import so you can't do b.withDescription() where b is a lvalue.
NextBuilder<Description> withDescription( string desc ) && {
m_buildingNode.description = desc;
return *this;
}
//other with* functions etc...
//needed so that if you store an incomplete builder in a variable,
//you can easily create a copy of it. This isn't really a problem
//unless you have optional values
NodeBuilder<flags> operator()() & {
return NodeBuilder<flags>(*this);
}
//Implicit cast from node builder to node, but only when building is complete
operator typename std::conditional<flags == (1 << TotalFlags) - 1, Node, void>::type() {
return m_buildingNode;
}
private:
Node m_buildingNode;
};
So for example:
NodeBuilder BaseNodeBuilder = NodeBuilder().withDescription(" hello world");
Node n1 = BaseNodeBuilder().withName("Foo"); //won't compile
Node n2 = BaseNodeBuilder().withValue("Bar").withName("Bob"); //will compile
Disclaimer: this is an idea. I'm not sure it even works. Just sharing.
You might try to:
remove build() method from NodeBuilder
regroup your mandatory fields into a single builder method of NodeBuilder, say NodeBuilder::withFieldData(bla, bli, blu) and/or NodeBuilder::withFieldData(structBliBlaBLU).
make withFieldData() to return a builder of a different type, say NodeBuilderFinal. Only this type of builder has build() method. You may inherit non-mandatory methods from NodeBuilder. (Strictly speaking, NodeBuilderFinal is a "Proxy" object)
This will enforce user to call withFieldData() before build(), while allowing to call other builder methods in arbitrary order. Any attempt to call build() on non-final builder will trigger compiler error. build() method will not show up in autocompletion until final builder is made ;).
If you don't want monolithic withFieldData method, you may return different proxies from each "field" method, like NodeBuilderWithName, NodeBuilderWithFile, and from those, you can return NodeBuilderWithNameAndFile, etc. until final builder will be built. This is quite hairy and will require many classes to be introduced to cover different orders of "field" calls. Similarly to what #ClaasBontus proposed in comments, you can probably generalize and simplify this with templates.
In theory, you may try to enforce more sophisticated constraints by introducing more proxy objects into the chain.
The only way I can imagine would be to have a number of static builder methods (or constructors) one for each set of required parameters that would return a builder instance, and then simple instance methods to set (or overwrite) parameters and that return the instance.
It will allow compile time checking, but at the price of a much more complex API, so I strongly advise you not to use it unless you really have good reasons to do.
This question can not be outdated. Let me share my solution to this problem.
class Car; //object of this class should be constructed
struct CarParams{
protected:
std::string name_;
std::string model_;
int numWheels_;
int color_;
struct Setter_model;
struct Setter_numWheels;
struct Setter_color;
public:
class Builder;
};
struct CarBuilder : CarParams{ //starts the construction
Setter_model& set_name(const std::string& name){
name_ = name;
return reinterpret_cast<Setter_model&>(*this);
}
};
struct CarParams::Setter_model : CarParams{
Setter_numWheels& set_model(const std::string& model){
model_ = model;
return reinterpret_cast<Setter_numWheels&>(*this);
}
};
struct CarParams::Setter_numWheels : CarParams{
Setter_color& set_numWheels(int numWheels){
numWheels_ = numWheels;
return reinterpret_cast<Setter_color&>(*this);
}
};
struct CarParams::Setter_color : CarParams{
Builder& set_color(int color){
color_ = color;
return reinterpret_cast<Builder&>(*this);
}
};
class CarParams::Builder : CarParams{
private:
//private functions
public:
Car* build();
// optional parameters
};
The class Car is defined bellow:
class Car{
private:
std::string name_;
std::string model_;
int numWheels_;
int color_;
public:
friend class CarParams::Builder;
//other functions
};
And build function in .cpp:
Car* CarParams::Builder::build(){
Car* obj = new Car;
obj->name_ = std::move(name_);
obj->model_ = std::move(model_);
obj->numWheels_ = numWheels_;
obj->color_ = color_;
return obj;
}
Maybe it is a little bit complicated, but looks nice on client side:
std::string name = "Name";
std::string model = "Model";
Car* newCar = CarBuilder()
.set_name(name)
.set_model(model)
.set_numWheels(3)
.set_color(0x00ffffff)
.build();
The error will occur in compile-time, if you miss something before build(). One more disadvantage is the strict order of arguments.
It can be combined with optional parameters.
Pointer to members are not used very much but they are really powerful, how have you used them and what's the coolest things you've done?
Edit:
This is not so much to list things that are possible, for example listing boost::bind and boost::function aren't good. Instead maybe a cool usage with them? I know they're very cool in themselves but that's not what this is about.
I once was needed to operate with criteria data as pure structure to be able to store the list of all criteria in the queue. And I had to bind the structure with the GUI and other filter elements, etc. So I came up with the solution where pointers to members are used as well as pointers to member functions.
Let's say you have an
struct Criteria
{
typedef std::string Criteria::* DataRefType;
std::string firstname;
std::string lastname;
std::string website;
};
Than you can wrap criteria field and bind with the string representation of the field with
class Field
{
public:
Field( const std::string& name,
Criteria::DataRefType ref ):
name_( name ),
ref_( ref )
{}
std::string getData( const Criteria& criteria )
{
return criteria.*ref_;
}
std::string name_;
private:
Criteria::DataRefType ref_;
};
Then you can register all the fields to use whenever you want: GUI, serialization, comparison by field names, etc.
class Fields
{
public:
Fields()
{
fields_.push_back( Field( "First Name", &Criteria::firstname ) );
fields_.push_back( Field( "Last Name", &Criteria::lastname ) );
fields_.push_back( Field( "Website", &Criteria::website ) );
}
template < typename TFunction >
void forEach( TFunction function )
{
std::for_each( fields_.begin(), fields_.end(),
function );
}
private:
std::vector< Field > fields_;
};
By calling for instance fields.forEach( serialization ); or
GuiWindow( Criteria& criteria ):
criteria_( criteria )
{
fields_.forEach( std::bind1st(
std::mem_fun( &GuiWindow::bindWithGui ),
this ) );
}
void bindWithGui( Field field )
{
std::cout << "name " << field.name_
<< " value " << field.getData( criteria_ ) << std::endl;
};
The coolest thing I've done with them, I did a long time ago. There's probably a better way to do it today.
I created a self-generating command-line parser for a network management tool. The classes representing the objects to be managed each had their own tables of sub-classes (name, pointer-to-factory-member), instances (id, pointer to instance from a list), and commands (name, pointer to member function). This allowed the parser to handle things like:
SET NETWORK ROUTE 192.168.0.0 HOPS 1
or
QUERY NETWORK NAMESERVER servername
without knowing anything about routes, or name servers.
Pointers to member function are great for creating psuedo lamba expressions with for_each
vector<SomeClass*> v = getAVector();
for_each(v.begin(), v.end(), mem_fun(&SomeClass::print));
Well I use pointers to member functions regularly with standard algorithms. There is nothing special about them as far as I am concerned.
You can bind member variables and functions with boost::bind and get usual functor.
Next work with them will like on usual functions usage:
passing as callback or signal function;
using in standard algorithms;
using as comparator in std::map/set;
using as data accessors;
In addition to the previous, you can for example use them as callback functions.
I did it in a "DomainEditor" class for this huge application I wrote. All my type (domain) tables in the database could be edited by the admins of the program and since the clients called some of the types by different names than others did, I made a dialog that allowed you to edit them. Well, I didn't want to make an editor for the 15+ domain types, so I wrote a super-class that I could cast each class to, and using pointers I could make simple calls to each domain table. Each one supported all the same properties, a Description (name), an ID, an Inactive flag, and a Required flag. So, the code started with a Macro to setup my calls:
#define DomainList(Class, Description, First, Next, Item, UpdateItem, DeleteItem, IsItemRequired, MaxLength) { \
CWFLHandler *handler = new CWFLHandler; \
handler->pWFL = new Class;\
handler->LoadFirstType = (LoadFirst)&Class::First;\
handler->LoadNextType = (LoadNext)&Class::Next;\
handler->LoadType = (Load)&Class::Item;\
handler->UpdateType = (Update)&Class::UpdateItem;\
handler->DeleteType = (Delete)&Class::DeleteItem;\
handler->IsRequiredType= (IsRequired)&Class::IsItemRequired; \
handler->MAX_LENGTH = MaxLength;\
PopulateListBox(m_Domain, Description, (long)handler); }\
Then, lots of calls to the Macro: (Here is just a single one)
DomainList(CConfigWFL, "Application Parameter Types", LoadFirstParameterType, LoadNextParameterType, LoadParameterTypeByTypeId, UpdateParameterType, DeleteParameterType, IsParameterTypeRequired, LEN_APPL_PARAMETER_DESC);
Then, the calls to edit the data were all common, and I didn't have to duplicate any code at all...
For example, to populate the list with the selected item in the DropDownList (populated by the Macro), the code would look like this:
if((pWFLPtr->pWFL->*pWFLPtr->LoadFirstType)(true))
{
do
{
m_Grid.AddGridRow();
m_Grid.SetCheck(COLUMN_SYSTEM, (pWFLPtr->pWFL->*pWFLPtr->IsRequiredType)(pWFLPtr->pWFL->TypeId));
m_Grid.SetCheck(COLUMN_STATUS, pWFLPtr->pWFL->InactiveIndc == false);
m_Grid.AddTextToGrid(COLUMN_NAME, pWFLPtr->pWFL->TypeDesc);
m_Grid.AddTextToGrid(COLUMN_DEBUG, pWFLPtr->pWFL->TypeId);
m_Grid.AddTextToGrid(COLUMN_ID, pWFLPtr->pWFL->TypeId);
}
while((pWFLPtr->pWFL->*pWFLPtr->LoadNextType)());
Of, course, this was all stored in a class that was part of the dialog. And I simply created new instances of the class, stored them in the ListBox's ItemData member. So, I did have to clean all that up when the dialog closed.. I left that code out of this message however.
The class to store all this stuff in was defined as:
typedef bool (CMyWFL::*LoadFirst)(bool);
typedef bool (CMyWFL::*LoadNext)();
typedef bool (CMyWFL::*Load)(long);
typedef bool (CMyWFL::*Update)(long, const char*, bool);
typedef bool (CMyWFL::*Delete)(long);
typedef bool (CMyWFL::*IsRequired)(long);
class CWFLHandler {
public:
CWFLHandler() {};
~CWFLHandler() { if(pWFL) delete pWFL; }
CMyWFL *pWFL;
LoadFirst LoadFirstType;
LoadNext LoadNextType;
Load LoadType;
Update UpdateType;
Delete DeleteType;
IsRequired IsRequiredType;
int MAX_LENGTH;
};
CWFLHandler *pWFLPtr;
All this work made it really nice to be able to add new domains to the application with very little work to add them to the domain editor... There may have been a better way, I don't know. But this is the way I went, and it worked VERY well for me, and IMHO, it was very creative... :)
I used them as part of a StructSerlialiser to populate C++ POD structures from SAX Parser events, i.e. to map XML onto a C++ data model.
template<class STRUCT, typename FIELDTYPE>
struct FieldBinderImpl : public FieldBinder<STRUCT>
{
typedef FIELDTYPE (STRUCT::*MemberPtr);
FieldBinderImpl (const std::string& tag, MemberPtr memberPtr)
: FieldBinder (tag)
, memberPtr_ (memberPtr)
{
}
virtual SerialiserBase* createSerialiser (STRUCT& data) const
{
return new Serialiser<FIELDTYPE> (&(data.*memberPtr_));
}
private:
MemberPtr memberPtr_;
};
template<class T>
class StructSerialiser : public SerialiserData<T>
{
public:
typedef std::vector<FieldBinder<T>*> FieldBinderList;
private:
static FieldBinderList fieldBinderList_;
protected:
template<typename FIELDTYPE>
static void bind (const std::string& tag, FIELDTYPE (T::* member))
{
fieldBinderList_.push_back (new FieldBinderImpl<T, FIELDTYPE> (tag, member));
if (tag.empty ())
fieldBinderList_.back ()->tags_ = Serialiser<FIELDTYPE>::getTags ();
}
// ...
}
// ...
Also had Serialisers for double, strings, vectors, etc. To use it you would just bind struct members to names, e.g.:
class Index
{
public:
std::string currency;
std::string name;
};
template<>
class Serialiser<Index> : public StructSerialiser<Index>
{
public:
Serialiser (Index* data) : StructSerialiser<Index> (data) {}
static void initialise ()
{
bind ("currency", &Index::currency);
bind ("name", &Index::name);
}
};