Trouble creating a class representing safely-ORrable flags - c++

I'm trying to create a small set of classes implementing a "safe flag" pattern, which would allow only predefined values to be OR-ed together. I've came up with something like that:
class MyClass;
class CreateFlag
{
friend class MyClass;
private:
int value;
CreateFlag(int newValue)
{
value = newValue;
}
public:
CreateFlag operator | (const CreateFlag & right) const
{
int newValue = value | right.value;
return CreateFlag(newValue);
}
CreateFlag(const CreateFlag && flag)
{
value = flag.value;
}
CreateFlag(const CreateFlag & flag)
{
value = flag.value;
}
static const CreateFlag Flag1;
static const CreateFlag Flag2;
static const CreateFlag Flag4;
};
const CreateFlag CreateFlag::Flag1 = CreateFlag(1);
const CreateFlag CreateFlag::Flag2 = CreateFlag(2);
const CreateFlag CreateFlag::Flag4 = CreateFlag(4);
class MyClass
{
public:
static void DisplayFlag(CreateFlag flag)
{
printf("Flag value: %d\n", flag.value);
}
};
int main(int argc, char * argv)
{
MyClass::DisplayFlag(CreateFlag::Flag1 | CreateFlag::Flag2);
getchar();
}
The problem is, that CreateFlag has a private ctor (what is intentional), so there is no way to specify the values of CreateFlag's static fields and the above code does not compile.
A way to bypass this restriction is to change static fields into static methods returning an instance of CreateFlag, but that's a dirty solution, as you would have to call the metod like:
MyClass::DisplayFlag(CreateFlag::Flag1() | CreateFlag::Flag2());
Is there a direct solution? If it changes anything, the flag definitions may be as well moved to the MyClass class.
I know also, that C++11 supports in-place initialization of static fields, but unfortunatelly VC++10 doesn't support this construct yet...
Edit I've modified the code, such that anyone can copy it and use, it compiles now and works as intended to.

The above code doesn't compile, but I think that it's not compiling for reasons beyond what you're expecting. Specifically, the compile error is in this line:
MyClass::DisplayFlag(CreateFlag::Flag1 | CreateFlag::Flag2);
The reason is that DisplayFlag takes its CreateFlag argument by value, and you've marked the copy constructor private.
If you're trying to ensure that people can't OR together invalid values, I don't think you need the copy constructor to be private. Making copies of CreateFlags that you know are valid doesn't allow clients to do anything that they previously couldn't do. If you omit the definition of the copy constructor and just let C++'s default copy support work for you, you should be just fine.
The lines that you've indicated as causing the error don't seem to cause any problems. It compiles just fine once you remove the copy constructor.
Hope this helps!

Related

C++ const "and the object has type qualifiers that are not compatible with the member

I'm new to C++ programming and in my OPP class we were requested to create a phone book.
Now, in the lecture the Professor said something about that if you want to make sure that your variable that is being injected to a method doesn't get changed you must put const on it.
here is my code so far.
private:
static int phoneCount;
char* name;
char* family;
int phone;
Phone* nextPhone;
public:
int compare(const Phone&other) const;
const char* getFamily();
const char* getName();
and in Phone.cpp
int Phone::compare(const Phone & other) const
{
int result = 0;
result = strcmp(this->family, other.getFamily());
if (result == 0) {
result = strcmp(this->name, other.getName);
}
return 0;
}
I keep getting "the object has type qualifiers that are not compatible with the member"
when I try to call to strcmp inside my compare function.
I know that I can just remove the const in the function declaration and it will go away, but I still doesn't understand why it's showing in the first place.
Help would be greatly appreciated.
You need to add const qualifier for getters const char* getFamily() const;. This way these getters can be invoked on objects of type const Phone & that you pass into function.
Also other.getName should be other.getName().
Your signature
int Phone::compare(const Phone & other) const
means inside that function you need to ensure you don't change the Phone instance.
At the moment, your function calls const char* getFamily() (and getName, which you've missed the () call from). Neither of these functions are const, hence the error.
If you mark these as const too, it will be ok.
In addition to the other answers that correctly suggest const qualifying your getters, you can access the data members of other directly, avoiding those calls.
int Phone::compare(const Phone & other) const
{
int result = strcmp(family, other.family);
if (result == 0) {
result = strcmp(name, other.name);
}
return result;
}

do_decimal_point and do_thousands_sep Not Working

do_decimal_point and do_thousands_sep seem to be completely ignored by my stream.
What I want is to do is use a period for my thousands_sep and a comma for my decimal_point in get_money. So I override moneypunct but it is just ignored :(
struct punct_facet : public moneypunct<char> {
char_type do_decimal_point() const { return ','; }
char_type do_thousands_sep() const { return '.'; }
};
int main()
{
istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
USCurrency.imbue(locale(locale("en-US"), new punct_facet));
int index = 0;
long double value;
do{
value = 0.0;
USCurrency >> get_money(value, true);
cout << ++index << ": " << value << endl;
} while (value == 123456.0 || value == -123456.0);
return 0;
}
I would expect this to just output:
1: 123
But instead I get:
1: 123456
2: -123456
3: 123
What am I doing wrong? I'm using Visual Studio 2013, in case that may be obvious from the "en-US".
EDIT:
I've discovered when I place a break-point in do_decimal_point or do_thousands_sep that it is never hit. I'm not sure why not, but that information seems to be relevant to the problem.
This solution is really just an explanation of the answer given here.
Both the copy constructor and assignment opperator are deleted by the moneypunct implementation. Which leaves two bad options for constructing punct_facet:
Duplicate all moneypunct members in punct_facet and call all moneypunct virtual functions in the punct_facet constructor to initialize them. This has the obvious drawback of a punct_facet object being twice as fat as it should be and it's constructor running longer than is strictly necessary.
Use pointers and a compiler specific knowledge of object layout to effect a copy construction from a moneypunct to a punct_facet. This has the obvious drawback of not being cross-platform and intentionally disregarding the standard implementation's design.
For this answer I have elected bad option 2, because the implementation of moneypunct is already compiler specific for any construction argument other than: "", "C", or "POSIX" and because there is an open bug against the deleted moneypunct copy constructor and assignment operator. (Incidentally if the moneypunct construction argument is adjusted option 2 works in gcc 5.1.0 as well, but it will not work in Clang 3.6.0.) Hopefully Microsoft will provide a more functional workaround for that bug soon and we won't have to use either bad option.
So if punct_facet is implemented like this:
template <typename T>
class punct_facet : public T {
private:
void Init(const T* money){
const auto vTablePtrSize = sizeof(void*);
memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
}
protected:
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
public:
punct_facet(){
Init(&use_facet<T>(cout.getloc()));
}
punct_facet(const T* money){
Init(money);
}
};
You can construct with either of the punct_facet constructors and you will get your expected output:
123
To use the default constructor you'd need to add cout.imdue(locale("en-US")); at the top of main and change your imdue statement to:
USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>()));
To use the custom constructor you'd only need to change your imdue statement to:
USCurrency.imbue(locale(locale("en-US"), new punct_facet<moneypunct<char, true>>(&use_facet<moneypunct<char, true>>(locale("en-US")))));
The default constructor is preferable as a discrepancy between your template type and your constructor argument could result in some bad behavior.
One minor note, your USCurrency is not using international currency format, so there's no need to use moneypunct<char, true>, moneypunct<char> will work just fine. Just remember to change it everywhere as a discrepancy between the template arguments to punct_facet and the arguments used in get_money will again result in the unexpected behavior you were seeing.

C++: Immutable method versions

In C++11, what is the best way to provide two versions of a method, one to modify the object itself and one to return a modified copy?
For example, consider a string class which has the "append(string)" method. Sometimes you might want to use append to modify your existing string object, sometimes you might want to keep your string object the same and create a copy.
Of course, I could just implement the first version and manually create a new object everytime I need one but that adds multiple temporary variables and lines of code to my project.
If it is still not clear what I am trying to do:
String s1("xy");
String s2 = s1.appendCopy("z");
s1.appendThis("w");
// s1 == "xyw"
// s2 == "xyz"
In Ruby there is a concept (or rather, a naming convention) which says for such methods, there are two variants: append (creates a new String) and append! (modifies this object)
C++ does not have something like this, so I would be stuck with ugly method names like "appendCopy".
Is there a good way to implement what I am trying to do?
So far, the best idea I had would be to make the modifying versions class members and the copying/immutable versions static methods which take the object to work on as a const argument.
There is actually a guideline, expressed by Herb Sutter in GotW #84:
Prefer non-member non-friend functions.
In your specific case, append (in-place) requires modifying the existing string so is well-suited to be a class-method, while append (copying) does not, so (following the guideline) should not be a class-method.
Thus:
void std::string::append(std::string const&);
inline std::string append(std::string left, std::string const& right) {
left.append(right);
return left;
}
After popular request, here are two overloads that can be used to optimize performance. First the member-version that may reuse its argument's buffer:
void std::string::append(std::string&& other) {
size_t const result_size = this->size() + other.size();
if (this->capacity() < result_size) {
if (other.capacity() >= result_size) {
swap(*this, other);
this->prepend(other);
return;
}
// grow buffer
}
// append
}
And second the free-function that may reuse its right-hand buffer:
inline std::string append(std::string const& left, std::string&& right) {
right.prepend(left);
return right;
}
Note: I am not exactly sure there are not ambiguous overloads manifesting. I believe there should not be...
With the new move semantics you can write:
class A{
public:
// this will get the property
const dataType& PropertyName() const { return m_Property; }
// this wil set the property
dataType& PropertyName() { return m_Propery; }
private:
dataType m_Propery;
};
main()
{
A a;
a.PropertyName() = someValueOfType_dataType; // set
someOtherValueOfType_dataType = a.PropertyName(); // get
}

QVariant comparison with own types working?

Update
I have created an qt bugticket hoping the documentation will be extended.
Original Question
Believing an Question from 2010 and the Qt Documentation, the operator==() doesn't work with custom types.
Quote:
bool QVariant::operator==(const QVariant & v) const
Compares this QVariant with v and returns true if they are equal; otherwise returns false.
QVariant uses the equality operator of the type() it contains to check for equality. QVariant will try to convert() v if its type is not the same as this variant's type. See canConvert() for a list of possible conversions.
Warning: This function doesn't support custom types registered with qRegisterMetaType().
I've tried to reproduce the repro case from the Stackoverflow Question from 2010 and the comparison worked without any problems for me.
I also went a step further and tried comparisons using an own class which also worked perfectly.
To reproduce, put the following code into any header:
enum MyEnum { Foo, Bar };
Q_DECLARE_METATYPE(MyEnum)
class MyClass
{
int value;
public:
MyClass() : value(0)
{
}
MyClass(int a) : value(a)
{
}
bool operator==(const MyClass &) const
{
Q_ASSERT(false); // This method seems not to be called
return false;
}
bool operator!=(const MyClass &) const
{
Q_ASSERT(false); // This method seems not to be called
return true;
}
};
Q_DECLARE_METATYPE(MyClass)
And the following code into any function:
QVariant var1 = QVariant::fromValue<MyEnum>(Foo);
QVariant var2 = QVariant::fromValue<MyEnum>(Foo);
Q_ASSERT(var1 == var2); // Succeeds!
var1 = QVariant::fromValue<MyEnum>(Foo);
var2 = QVariant::fromValue<MyEnum>(Bar);
Q_ASSERT(var1 != var2); // Succeeds!
QVariant obj1 = QVariant::fromValue<MyClass>(MyClass(42));
QVariant obj2 = QVariant::fromValue<MyClass>(MyClass(42));
Q_ASSERT(obj1 == obj2); // Succeeds!
obj1 = QVariant::fromValue<MyClass>(MyClass(42));
obj2 = QVariant::fromValue<MyClass>(MyClass(23));
Q_ASSERT(obj1 != obj2); // Succeeds!
I would guess that in newer qt versions the size of a type is aquired when the Q_DECLARE_METATYPE is used so the QVariant can compare values of unknown types bytewise.
But that's only a guess and I don't want to risk the stability of my application by guessing what qt does instead of relying on the documentation.
Can I find out, how the QVariant compares unknown types? I would prefer relying on specification than on implementation.
I'm afraid you'll need to rely on the code (and, being behaviour, it can't be changed without breaking), and not documentation. There's a surprise just below, though.
Here's the relevant code.
QVariant::operator== for types with unregistered operators will just use memcmp. The relevant snippet (in 5.1) is this:
bool QVariant::cmp(const QVariant &v) const
{
QVariant v1 = *this;
QVariant v2 = v;
if (d.type != v2.d.type)
// handle conversions....
return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);
}
handlerManager is a global object that gets used to perform type-aware manipulations. It contains an array of QVariant::Handler objects; each of such objects contains pointers to perform certain operations on the types they know how to handle:
struct Handler {
f_construct construct;
f_clear clear;
f_null isNull;
f_load load;
f_save save;
f_compare compare;
f_convert convert;
f_canConvert canConvert;
f_debugStream debugStream;
};
Each and every of those members is actually a pointer to a function.
The reason for having this array of global objects is a bit complicated -- it's for allowing other Qt libraries (say, QtGui) to install custom handlers for the types defined in those libs (f.i. QColor).
The operator[] on the handlerManager will perform some extra magic, namely get the right per-module handler given the type:
return Handlers[QModulesPrivate::moduleForType(typeId)];
Now the type is of course a custom type, so the Handler returned here is the one the Unknown module. That Handler will use the customCompare function in qvariant.cpp, which does this:
static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
{
const char *const typeName = QMetaType::typeName(a->type);
if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(a->type)))
qFatal("QVariant::compare: type %d unknown to QVariant.", a->type);
const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
uint typeNameLen = qstrlen(typeName);
if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
if (a->is_null && b->is_null)
return true;
return !memcmp(a_ptr, b_ptr, QMetaType::sizeOf(a->type));
}
Which, apart from a bit of error checking and handling shared and null variants in a special way, uses memcmp on the contents.
... only if the type is not a pointer type, it seems. Wonder why there's that code there...
Good news!
Starting with Qt 5.2, you can use QMetaType::registerComparator (see here) to make Qt invoke operator< and operator== on your custom type. Just add to your main:
qRegisterMetaType<MyClass>();
QMetaType::registerComparators<MyClass>();
And voilĂ , you'll hit the assert in your equality operator. QVariant::cmp now is:
QVariant v1 = *this;
QVariant v2 = v;
if (d.type != v2.d.type)
// handle conversions, like before
// *NEW IMPORTANT CODE*
if (v1.d.type >= QMetaType::User) {
// non-builtin types (MyClass, MyEnum...)
int result;
// will invoke the comparator for v1's type, if ever registered
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d)), v1.d.type, &result))
return result == 0;
}
// as before
return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);

Subscripting a reference to const

I'm here looking at some C++ code and am not understanding something. It is irrelevant but it comes from a YARP (robot middleware) tutorial which goes with the documentation.
virtual void getHeader(const Bytes& header)
{
const char *target = "HUMANITY";
for (int i=0; i<8 && i<header.length(); i++)
{
header.get()[i] = target[i];
}
}
Now, header is a reference to const and thus cannot be modified within this function. get is called on it, its prototype is char *get() const;. How can header.get() be subscripted and modified ? The program compiles fine. I may have not understood what happens here but I'm basing myself on what I've read in C++ Primer...
I would very much appreciate a little clarification!
Have a nice day,
char *get() const;
The right hand const means "this member doesn't alter anything in the class that's not mutable", and it's honoring that - it isn't changing anything. The implementation is probably something like this:
char *Bytes::get() const
{
return const_cast<char *>(m_bytes);
}
The pointer that is being returned, however, is a simple "char*". Think of it this way:
(header.get())[i] = target[i];
// or
char* p = header.get();
p[i] = target[i];
Whoever designed the interface decided that the content of a const Byte object can be modified by stuffing values into it. Presumably they've done whatever hacks they needed to make header.get()[i] modifiable. I wouldn't use this code as an exemplar of good interface design.
Looking at the doc:
struct Bytes {
char* get() const; // works
char*& get() const; // would not work
char* mem_;
};
This code is perfectly valid, even though it is bad practice. The
problem is that a copy of the pointer is made and the constness of the
class is lost. constness in C++ is largely conceptual and easy to
break (often even without consequences). I'd complain to the
implementer. It should look like this:
struct Bytes {
char* get(); // works
const char* get() const; // would not work
char* mem_;
};
header.get() should returns char*, assuming it as base address and indexed with [i] and string in target coped to that location.
#antitrust given good point, return address can't be modified by address content can e.g.
char x[100];
char* get() const
{
return x;
}
int calling function you can do like:
get()[i] = target[i];
it will copy target string to x, this method can be useful when x is private member to class, and you are to copy in x.
Edit if get() is a inline function then calling get() function in a loop will not effect performance., I mean such function should be defined inline.