I have a problem with enum classes, QVariants and the QSettings class. There are enum class values that I want to store within a QVariant which goes into a QSettings instance. So, my code actually looks something like this:
enum class Foo
{
Bar1, Bar2
}
Q_ENUMS(Foo)
Q_DECLARE_METATYPE(Foo)
...
Foo value = Bar2;
QSettings settings;
settings.setValue(QString("Foo"), QVariant::fromValue(value));
At this point in executing the code, an assertion jumps in and complains:
ASSERT failure in QVariant::save: "Invalid type to save", file kernel\qvariant.cpp
Searching the internet, I found out that the class is missing a fitting << and >> operator. But that is not an option for enum classes. I even tried to use
qRegisterMetaType<Foo>("Foo");
but it did not help. Maybe you have some other suggestions/solutions for me. Thanks!
Enums, which are masked unsigned ints, seem to be a problem, see
Qt4 QSettings save enumeration value (for example Qt::CheckState)
The solution there and probably here would be to convert it an unsigned. To check if the static_cast-result back to the enum is valid you might add Foo_lowest and Foo_highest values to the beginning and end of the enum range.
You can use Q_ENUM since Qt 5.5 and not worry about calling qRegisterMetaType():
enum class Foo
{
Bar1, Bar2
}
Q_ENUM(Foo)
...
Foo value = Foo::Bar2;
QSettings settings;
settings.setValue(QString("Foo"), QVariant::fromValue(value));
Related
I want to be able to retrieve the names for the types in an enumeration without having to actually assign a variable to them. Hence, given an enumeration like this
class my_class;
typedef enum bit {
ONE,
TWO
} fsm_state_t;
endclass
I know I can access the name of a declared variable like this:
class another_class;
...
my_class::fsm_state_t state = my_class::ONE;
print(state.name());
...
endclass
Is it possible to access the names of the enum without actually having to declare and assign a variable? What I mean is something like this:
class another_class;
...
print(my_class::ONE);
print(my_class::TWO);
...
endclass
No, built-in methods cannot be called on types.
if someday the type is changed, the compiler notifies that the print
must be changed as well.
By simply "using" the enumeration within your code, if it goes away you'll get a compile error. That seems to be what you're duplicating. A more practical duplication would be to value check every enum:
class another_class;
...
if (my_class::ONE!=0) print("ONE has changed!");
if (my_class::TWO!=1) print("TWO has changed!");
...
endclass
EDIT: or create a wrapper class for enums
virtual class enum_wrap#(type T);
static function string name(T obj);
return obj.name();
endfunction
endclass
program testbench;
initial begin
typedef enum {ZERO, ONE, TWO, THREE} numbers_t;
$display("ENUM without variable: %s", enum_wrap#(numbers_t)::name(THREE));
end
endprogram
prints:
ENUM without variable: THREE
Universal references as parameter or return type
I read a few articles about universal references but I still don't understand in which cases I might need to use this as a parameter type besides the move constructor. Could someone enlighten me?
void Foo(Bar&& x);
Bar&& Foo();
Under which circumstances would I ever want to have this which I couldn't solve with a simple Bar& to move something?
When to use std::move
Could someone explain me when an explicit std::move is necessary (for parameters and return types) under which circumstances I can expect that the compiler uses it automatically during the optimization phase? For example
struct A { A(A&& src) ... };
A Foo()
{
A a;
...
return a;
}
In this case I might benefit from RVO, so should I even ever consider using std::move for a result? Thanks a lot!
Universal references
The example you've provided doesn't actually use universal references, those are just r-value references. Syntactically, the universal reference is an r-value reference to a parameter of a deduce templated type:
template <typename Bar>
void foo(Bar &&bar);
This is actually different then a regular r-value reference and it is used to solve a perfect forwarding problem. But I assume this isn't what your question is about.
R-value references
In most cases when you want to move the value to or from the function you can simply do it by value:
void foo(Bar b);
...
Bar somebar;
foo(std::move(somebar)); //function argument is move-constructed
/**************************************************************/
Bar foo()
{
Bar somebar;
return somebar; //return value is move-constructed
}
Doing this using l-value reference is actually incorrect:
void foo(Bar &b)
{
Bar somebar = std::move(b); //you "stole" passed value
}
...
Bar somebar;
foo(somebar); //but the caller didn't intend to move his value
Also returning any reference to a local variable is wrong.
The only reason one would use r-value reference instead of passing by value is to allow moving the value without actually moving it one extra time:
Bar &&Foo::foo()
{
return memberBar;
}
...
Foo f;
Bar b = f.foo(); //"b" will be move-constructed
...
f.foo().doBar(); //returned "Bar" value is just used and not moved at all
When to use std::move
You need to use std::move every time you want to move a variable even if it's already an r-value reference:
Foo::Foo(Bar &&bar)
: memberBar(std::move(bar)) //still need to move explicitly!
{
}
You don't need to use std::move when:
Returning a local variable by value
Passing a temporary to a function, e.g. foo(Bar())
Passing non-movable types (those without move-constructor) including primitive types
A common mistake:
Bar *bar = new Bar();
foo(std::move(bar)); //not needed! nothing to move since the pointer is passed and not the object itself
However when using a conditional operator:
Bar foo()
{
Bar somebar;
Bar otherbar;
return std::move(true ? somebar : otherbar); //need to move explicitly!
}
In 'modern' C++ that suppports strongly typed enums: is the class keyword optional?
I saw code that defines enums like:
enum SomeEnum: unsigned int {
VAL1 = 0,
VAL2 = 1,
// ...
};
Is this a different thing, a sloppyness of the compiler (VS 2015 (MSVC 19)) or is the class keyword implicit if the enum is strongly typed?
The code in the question declares a normal unscoped enumeration, whose underlying type is however fixed. So it is different from enum class because it still does not introduce a scope for its enumerators.
Since c++11 even normal enums (which still exist) can accept an underlying type specification. See here.
enum-key attr(optional) identifier(optional) enum-base(optional)(C++11) { enumerator-list(optional) }
Emphasis mine
So it is a normal enum not a enum class but with a enum-base specification.
What you call "strongly typed enum" is really named scoped enumerations, and for those the class or struct keyword is mandatory.
Using the "inheritance" syntax is not part of scoped enumerations, they can be used for normal unscoped enumerations as well.
Being a little new to OOP concepts, enums in Kotlin are a bit confusing to me. My caveman interpretation is that enums are used to store non changing variables. I'm making a simple Tic-Tac-Toe app and simply want to store the values 'X', 'Y', and '-' all as Chars. Where is my confusion? Is there a better way to retrieve a particular set of Chars from a "library"? Here is my current assumption in code:
enum class markers(char: Char){
X('X'), O('O'), EMPTY('-')
}
//To access the enums, thought it would be something like this
fun printX(){
println(markers.X)
}
You want to have the property char instead of the enum constants‘ name, change to:
fun printX(){
println(markers.X.char)
}
Also make char a val so that it’s accessible as a property: enum class markers(val char: Char)
enum class markers(private val char: Char){
X('X'), O('O'), EMPTY('-');
override fun toString() = char.toString()
}
markers.values().forEach(::print)
I write a program with my class:
class COrder
{
public:
COrder();
~COrder();
public:
...
CList < CItem > m_oItem;
...
};
which suppose to have list od object of my other class:
class CItem
{
public:
CItem();
~CItem();
public:
int m_i;
double m_d;
CString m_o;
};
and compiler give me error like this in title. Any ideas why ?
In program I use COrder in map:
CMap <CString, LPCTSTR, COrder, COrder> m_map
Quote:
Add copy-constructor and assignment operator to your class COrder.
I add operator= to my class:
COrder& operator=( const COrder oNewOrder )
{
...
m_oItem.AddTail( oNewOrder.m_oItem.GetTail() );
...
return *this;
}
but what you mean by adding "copy-constructor" ?
http://msdn.microsoft.com/en-us/library/ccb3dh5c.aspx i found this but how to implement it in my code. i can't change CList class.
http://www.codeproject.com/Articles/13458/CMap-How-to
Add copy-constructor and assignment operator to your class COrder. This makes the class copyable.
[If class is used in as Key then you need HashKey() and CompareElemenst() in that class]
Also note that STL containers are superior to MFC containers.
You get an error because CMap has default copy-ctor but CMap and CList is derived from CObject and CObject declares private copy constructor and operator=.
So, CMap doesn't offer a copy semantic "out of the box".
I would suggest you to use STL std::map container, which is designed in a
way to implement copy semantic out-of-the-box.
What you don't have with STL out of the box is serialization only.
Note that std::map does not have the confusing ARG_KEY and ARG_VALUE
templates.
std::map just has the Key and Type template arguments (in its basic form).
http://msdn.microsoft.com/en-us/library/s44w4h2s%28VS.80%29.aspx
Or else you can go by the pointer way as Ajay suggested by which you will just shut up the compiler.
The problem statement:
CList<CItem> m_oItem;
And the trigger statement (or some usage):
CMap <CString, LPCTSTR, COrder, COrder> m_map;
Why? Well, CMap would call copy constructor and/or assignment operator for COrder. You didn't provide any, but compiler provides them from your class (i.e. for COrder). This class contains a CList object, which is inherited from CObject. CObject doesn't provide (or better say: Prevents) copy-constructor or assignment operator.
As a result, the compiler raises the error. Unfortunately, the (bad) compiler doesn't give you back-trace of this error.
Best bets for as the solution:
CList < CItem* > m_oItem;
CList<CItem> *m_poItem;
Use or implement your own collection.