I have defined the classes 'Outcome' and 'Bin'.
I am trying to pass an array of type Outcome to a Bin Constructor, in order to add each element of that array to a set of 'Outcome's that is a member property of the Bin Class.
//Bin.h
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
Bin(Outcome Outcs[], int numberofelements);
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
//In Bin.cpp
Bin::Bin(Outcome outcs[], int numberofelements) {
int i;
for (i=0;i<(numberofelements-1);i++) {
outcomeset.insert(outcs[i]); //When this LIne is commented out, no compile errors!
}
}
This results in a whole mess of errors in VS2010 that link back to library files. I have been unable to find anything online or in my "The Big C++" textbook. Is this a completely wrong implementation of this sort of functionality? Or am I missing something rather basic?
For the curious I am implementing this as part of the 'Roulette' Problem from this free textbook http://www.itmaybeahack.com/homepage/books/oodesign.html
Thanks for your help!
EDIT: I have added the (rather lengthy) error text to a pastebin, here: http://pastebin.com/cqe0KF3K
EDIT2: I have implemented the == != and < operators for the outcome class, and the same line still does not compile. Here are the implementations
//Outcome.cpp
bool Outcome::operator==(Outcome compoutc) {
if (mEqual(compoutc) == true) {
return true;
}
else {
return false;
}
}
bool Outcome::operator!=(Outcome compoutc) {
if (mEqual(compoutc) == false) {
return true;
}
else {
return false;
}
}
bool Outcome::operator<(Outcome compoutc) {
if (odds < compoutc.odds) {
return true;
}
else {
return false;
}
}
EDIT3: Implemented the comparison operator with the de-referenced parameter and const tags and now it compiles!
You need to define an operator< for the class being inserted into the set.
Also note that instead of an explicit loop, you're probably better off using a pair of "iterators" (pointers, in this case) and actually initializing the set:
#include <set>
#include <string>
class Outcome {
int val;
public:
bool operator<(Outcome const &other) const {
return val < other.val;
}
Outcome(int v = 0) : val(v) {}
};
class Bin {
private:
std::set<Outcome> outcomeset;
public:
Bin();
// Actually initialize the set:
Bin(Outcome Outcs[], int n) : outcomeset(Outcs, Outcs+n) {}
Bin(std::set<Outcome> Outcs);
void add(Outcome Outc);
std::string read();
};
int main() {
// Create an array of Outcomes
Outcome outcomes[] = {Outcome(0), Outcome(1) };
// use them to initialize the bin:
Bin b((outcomes),2);
return 0;
}
Related
I have the following snippet of code that seems to be making use of predicates but I am unable to figure out what (elem.*predicator)() does. I tried looking for some easier to understand documentation regarding the same on the web as well as SO (closest thing I found was this) but couldn't find anything that could help me.
The code:
using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
The struct OperationPointInfo is as follows:
struct OperationPointInfo {
// The shelf in this operation point. -1 for empty.
int shelf_id;
bool scheduled_to_change;
// The time point the shelf was moved into the operation point, in the format of seconds since epoch.
TimePoint start_time;
// Index for this operation point.
int index;
OperationPointInfo() {
OperationPointInfo(-1);
}
OperationPointInfo(int index) : index(index) {
shelf_id = -1;
scheduled_to_change = false;
}
bool CapableForMoveOut() const {
return shelf_id >= 0 && !scheduled_to_change;
};
bool CapableForMoveIn() const {
return shelf_id < 0 && !scheduled_to_change;
};
};
The function which has got me baffled is this one:
template<class T>
std::optional<T> ReserviorSamplingOperationPoint(const vector<T> &array, bool (T::*predicator)(void) const) {
T selected;
bool found = false;
int counter = 1;
for (const auto &elem : array) {
if ((elem.*predicator)()) {
selected = elem;
found = true;
counter++;
}
}
if (found) {
return selected;
} else {
return nullopt;
}
}
Where the above function is being called:
void GenSpToOpMissions() {
std::vector<OperationPointInfo> operation_point_info_;
auto to_or_empty = ReserviorSamplingOperationPoint(operation_point_info_, &OperationPointInfo::CapableForMoveIn);
OperationPointInfo to = to_or_empty.value();
}
.* and ->* are the pointer-to-member operators.
Those are pointers that can store which method of a class to call.
See [expr.mptr.oper] in the standard or questions like Calling C++ class methods via a function pointer.
What is the method to save and retrieve contents (to/from a disk file) of an object who has const member variables?
Or more specifically, const members demand an initialization at the creation time of the object. So, the retrieval of the content has to happen before the initializers (before { } of the constructor). If we are not minding the encapsulation, we can retrieve and create the object with parameters. How to do everything by keeping the data-hiding?
Compiler: C++ 14 and maybe beyond.
Instantiation of the object, filling the content and storing for next context.
{ //CODE BLOCK 1 : making of content and saving to a diskfile
Abcd abcd(65535,256,25);
//some operations on abcd
//save to disk
QFile abcdFile("abcd.lion");
abcdFile.open(QFile::WriteOnly);
abcd.serialize(abcdFile);
abcdFile.close();
}
using same object after taking from file.
{ //CODE BLOCK 2 : loading from file and continue in another context
QFile abcdFile("abcd.lion");
abcdFile.open(QFile::ReadOnly);
Abcd abcdNew(abcdFile);
abcdFile.close();
if(!abcdNew.isHealthy())
printf("abcd from hdd is NOT Healthy :(\n");
else
{
//doTheJob(abcdNew);
}
}
The class.
#include <QFile>
class Abcd
{
const bool _healthy;//true if properly initialized
//IMPORTANT: _healthy has to be the first member in the class.
//this is to execute its initializer list first
protected:
const long _rX;
const long _rY;
long _count;
public:
Abcd(const long refX,
const long refY,
const long count) :
_healthy(true),
_rX(refX), _rY(refY),
_count(count)
{
}
Abcd(QFile &src) :
_healthy(deserialize(src)),
//Hack. Actually the initialization happened by this statement.
//just keeping the below statements for the sake of syntactical correctness. :(
_rX(_rX), _rY(_rY)
//,_count(count)
{
}
virtual
~Abcd()
{
}
inline
bool isHealthy()
{
return _healthy;
}
bool serialize(QFile &dest)
{
if(dest.write((char *)&_rY,sizeof(_rY))!=sizeof(_rY)) return false;
if(dest.write((char *)&_rX,sizeof(_rX))!=sizeof(_rX)) return false;
if(dest.write((char *)&_count,sizeof(_count))!=sizeof(_count)) return false;
return true;
}
private:
bool deserialize(QFile &src)
{
if(src.read((char *)&_rY,sizeof(_rY))!=sizeof(_rY)) return false;
if(src.read((char *)&_rX,sizeof(_rX))!=sizeof(_rX)) return false;
if(src.read((char *)&_count,sizeof(_count))!=sizeof(_count)) return false;
return true;
}
};
Please suggest a better method. For this, I have introduced a ‘healthy’ status member as the first member in the declaration of the class. Also in deserialization, I am fooling the compiler by casting the const variable to char * pointer.
My suggestion will be to use a static member function of the class to retrieve the contents of the file from disk and construct an object after the contents have been retrieved successfully.
Instead of:
Abcd(QFile &src) :
Use
static Abcd deserialize(QFile& src);
and implement it as:
Abcd Abcd::deserialize(QFile& src)
{
long rX;
long rY;
long count;
if(src.read((char *)&rY, sizeof(rY)) != sizeof(rY)) throw false;
if(src.read((char *)&rX, sizeof(rX)) != sizeof(rX)) throw false;
if(src.read((char *)&count, sizeof(count)) != sizeof(count)) throw false;
return Abcd(rX, rY, count):
}
PS It's strange that you save _rY first and then _rX. There is nothing wrong, it's just strange.
My suggestion is to split up the logic of Abcd and serialization/deserialization into two classes.
Benefits:
no field _healthy as object is always valid by design.
class Abcd does only one job. Is free from any logic of storing (Single responsibility)
Few hints:
RVO is mandatory since c++ 17
const fields just make the object not copy/move assignable (unable to use with containers etc.). Simply properly use const correctness to ensure immutability.
do not inherit implementation, only interfaces: Abcd is final, no virtual methods - better performance.
follow the Cpp Core Guidelines
class Abcd final
{
public:
Abcd(const long refX, const long refY, const long count)
: _rX(refX)
, _rY(refY)
, _count(count)
{
}
long GetRX() const
{
return _rX;
}
long GetRY() const
{
return _rY;
}
long GetCount() const
{
return _count;
}
protected:
long _rX;
long _rY;
long _count;
};
#include <boost/optional.hpp>
#include <QFile>
template <typename T>
using Opt = boost::optional<T>; // or equivalent
// Choose better name for Serializer or even split it up
class AbcdSerializer final
{
public:
AbcdSerializer(QFile& file)
: _file(file)
{
}
// You may also throw an exception instead of returning optional
Opt<Abcd> TryDeserializeAbcd()
{
long rX;
long rY;
long count;
if (ReadValue(rY) && ReadValue(rX) && ReadValue(count))
{
return Abcd(rX, rY, count);
}
return {};
}
bool SerializeAbcd(const Abcd& abcd)
{
return WriteValue(abcd.GetRY()) && WriteValue(abcd.GetRX()) && WriteValue(abcd.GetCount());
}
private:
template <typename T>
bool ReadValue(T& value)
{
constexpr auto ValueSize = sizeof(value);
return _file.read(reinterpret_cast<char*>(&value), ValueSize) != ValueSize;
}
template <typename T>
bool WriteValue(const T& value)
{
constexpr auto ValueSize = sizeof(value);
return _file.write(reinterpret_cast<const char*>(&value), ValueSize) != ValueSize;
}
QFile& _file;
};
I'm trying to modify a bool field in a method. The method accepts a pointer pointer bool, but can't seem to figure it out how to do this correctly.
This is a basic example of something similar I want to do:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool ** warning) {
**warning = true;
}
}
This code example errors (sending bool* but needs to be bool**) and I've tried other ways with no luck. Can't find any online examples but maybe I'm searching for the wrong terms. What is the right way to do this?
Since you have a class, no parameters are required.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning()
}
void pushWarning() {
seenWarningA = true;
}
}
Using references rather than pointers is more elegant.
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA)
}
void pushWarning(bool & warning) {
warning = true;
}
}
If you want to use pointers, the & operator just gives single pointer rather than a double point:
class WarningManager {
bool seenWarningA;
void updateWarnings() {
pushWarning(&seenWarningA)
}
void pushWarning(bool * warning) {
*warning = true;
}
}
You appear to be trying to pass an argument of bool* into a function that takes bool**. Remove one of the layers of indirection from the parameter list, or add one to the value you're passing in. Either should work.
Two mistakes:
First- your declaration of pushWarning is with parameter of type bool**, and you are trying to send bool*.
Second- you can simply use reference:
using namespace std;
class WarningManager {
public:
bool seenWarningA;
void updateWarnings() {
pushWarning(seenWarningA);
}
void pushWarning(bool &warning) { // You can simply use refference instead of pointer to pointer, or pointer at all..
warning = true;
}
};
int main()
{
WarningManager w;
w.seenWarningA = false;
w.updateWarnings();
cout << w.seenWarningA; // Prints 1
return 0;
}
I have class called "UltrasoundTemplate". These UltrasoundTemplate objects contain an int parameter, which shows when they where defined (something like a time stamp). And I have a class called "UltrasoundTarget" which contains a vector of UltrasoundTemplate's.
I add UltrasoundTemplates to the vector with push_back(ultrasoundTemplate).
Now I want to sort the vector by the order of time stamps instead of the order I added them to the vector.
I found a lot of answers in google, which all show me the same solution, but obviously I'm still doing something wrong. Here are the code snippets I think are necessary for finding a solution:
ultrasoundTemplate.h
class UltrasoundTemplate
{
public:
UltrasoundTemplate(/*...*/);
int getVolumePos() { return volume_; }
private:
int volume_;
};
ultrasoundTarget.h
//the sort algorithm
struct MyTemplateSort {
bool operator() ( UltrasoundTemplate t1, UltrasoundTemplate t2){
int it1 = t1.getVolumePos();
int it2 = t2.getVolumePos();
if (it1 < it2)
return true;
return false;
}
};
class UltrasoundTarget
{
public:
UltrasoundTarget(/*...*/);
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; }
private:
vector<UltrasoundTemplate> USTemplateVector_;
};
FMainWindow.cpp
void FMainWindow::match_slot()
{
int i;
//here I get the name of the target I'm looking for
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem();
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item);
QString itemToAppendName = item->text(0);
for(i = 0; i < USTargetVector.size(); i++){
if(USTargetVector.at(i).getName() == itemToAppendName) {
//here I try to sort
MyTemplateSort tmpltSrt;
std::sort(USTargetVector.at(i).getTemplates().begin(),
USTargetVector.at(i).getTemplates().end(), tmpltSrt);
break;
}
}
As an example: I define Template1 in Volume(0), Template2 in Volume(70) and Template3 in Volume(40). The order now is (Template1, Template2, Template3) but I want it to be (Template1, Template3, Template2). But this code is not doing it.
If there's Information missing, just tell me and I'll provide more code.
Thanks alot.
Your getTemplates() method returns by value, making a mess here:
std::sort(USTargetVector.at(i).getTemplates().begin(),
USTargetVector.at(i).getTemplates().end(), tmpltSrt);
You are sorting an incompatible iterator range. You can fix that particular problem by returning a reference:
vector<UltrasoundTemplate>& getTemplates() { return USTemplateVector_; }
It is common practice to add a const overload to such a method:
const vector<UltrasoundTemplate>& getTemplates() const { return USTemplateVector_; }
You can also modify your comparison functor to avoid unnecessary copies (and for general readability and const correctness):
struct MyTemplateSort {
bool operator() const ( const UltrasoundTemplate& t1, const UltrasoundTemplate& t2)
{
return t1.getVolumePos() < t2.getVolumePos();
}
};
This will require that you make getVolumePos() a const method, which it should be anyway:
class UltrasoundTemplate
{
public:
...
int getVolumePos() const { return volume_; }
...
};
Note that is is not generally good practice to provide references to the private data of a class. If possible, you should find a way to remove that from the UltraSoundTarget interface. You could, for instance, expose a pair of iterators, and/or give the class a sort method.
juanchopanza answer is correct, the problem is the way you are returning the vector from UltrasoundTarget. Just to touch another topic, maybe it would be nice to change a little the designing of your implementation. As UltrasoundTarget is a container of Ultrasound's, it makes sense to implement the sort as a method of this class, this way you have direct access to USTemplateVector_ and will save unecessary copies. Something like:
class UltrasoundTarget
{
public:
UltrasoundTarget(/*...*/);
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; }
void sort();
private:
vector<UltrasoundTemplate> USTemplateVector_;
};
void UltrasoundTarget::sort()
{
std::sort(USTemplateVector_.begin(), USTemplateVector_.end(), tmpltSrt);
}
void FMainWindow::match_slot()
{
int i;
//here I get the name of the target I'm looking for
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem();
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item);
QString itemToAppendName = item->text(0);
for(i = 0; i < USTargetVector.size(); i++){
if(USTargetVector.at(i).getName() == itemToAppendName)
{
//here I try to sort
MyTemplateSort tmpltSrt;
USTargetVector.at(i).sort();
break;
}
}
Working on a large project concerning C++ and Matlab cooperation through Mex we are currently struggling with one of our singletons.
The class is being generated through macros during preprocessing so it may seem a bit odd.
class AdditionalOperation {
private:
const std::string* val;
typedef std::map<std::string, const std::string*> StringMap;
static StringMap& getStringToPointerMap()
{
static StringMap map;
return map;
}
static boost::mutex& getMutex()
{
static boost::mutex mutex;
return mutex;
}
AdditionalOperation(const std::string* s)
:val(s)
{}
private:
static std::string* none_string()
{
static std::string s = "none";
static int count = 0;
boost::mutex::scoped_lock lock(getMutex());
if(count++ == 0) {
getStringToPointerMap().insert(std::make_pair(s,&s));
}
return &s;
}
public:
static AdditionalOperation none()
{
return AdditionalOperation(none_string());
}
private:
static std::string* norm_string()
{
static std::string s = "norm";
static int count = 0;
boost::mutex::scoped_lock lock(getMutex());
if(count++ == 0) {
getStringToPointerMap().insert(std::make_pair(s,&s));
}
return &s;
}
public:
static AdditionalOperation norm()
{
return AdditionalOperation(norm_string());
}
private:
static void prepare()
{
none();
norm();
}
public:
static AdditionalOperation fromString(std::string s)
{
static int count = 0;
if(count++ == 0)
prepare();
boost::mutex::scoped_lock lock(getMutex());
StringMap& map = getStringToPointerMap();
StringMap::iterator location = map.find(s);
if(location == map.end()) {
throw UnknownEnumValue(s);
}
return AdditionalOperation(location->second);
}
std::string toString() const
{
return *val;
}
bool operator==(const AdditionalOperation& other) const
{
return val == other.val;
}
bool operator!=(const AdditionalOperation& other) const
{
return !(*this == other);
}
};
All this code is generated from this line (through macros as stated above):
DECLARE_SENUM(AdditionalOperation, none, norm);
Which is a nice interface that we'd like to keep on using.
We want to use this class as a replacement for enumerations because we need to translate them from string and to a string. In this class we have 2 'enumeration' members namely norm and none.
Now we have added some logging and have determined that the insert operation inside the none_string and norm_string function is being called twice even though our counter should prevent this.
Some things we have tried :
We are working with a dynamic library but using -rdynamic did not help.
When we print the address of the static variables we can clearly see that they differ.
This class is situated within a dynamic library which in turn is linked with a mex file. This mex file is being dynamically loaded by another mex file through dlopen.
We were thinking that perhaps multiple instances of this class are declared and active because of the dynamic library. But we also use other kind of singletons that have not shown any sign of problems.
I hope it was clear enough, additional information or clarification can always be provided!
Thanks in advance!
You are, clearly, overcomplicating the problem.
std::string const& to_string(MyEnum e) {
static std::string const First = "First";
static std::string const Second = "Second";
switch(e) {
case MyEnum::First: return First;
case MyEnum::Second: return Second;
}
throw std::runtime_error("Unknown enum value");
}
would work as well, if not better and faster.