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
Related
With the struct definition given below...
struct A {
virtual void hello() = 0;
};
Approach #1:
struct B : public A {
virtual void hello() { ... }
};
Approach #2:
struct B : public A {
void hello() { ... }
};
Is there any difference between these two ways to override the hello function?
They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.
The 'virtualness' of a function is propagated implicitly, however at least one compiler I use will generate a warning if the virtual keyword is not used explicitly, so you may want to use it if only to keep the compiler quiet.
From a purely stylistic point-of-view, including the virtual keyword clearly 'advertises' the fact to the user that the function is virtual. This will be important to anyone further sub-classing B without having to check A's definition. For deep class hierarchies, this becomes especially important.
The virtual keyword is not necessary in the derived class. Here's the supporting documentation, from the C++ Draft Standard (N3337) (emphasis mine):
10.3 Virtual functions
2 If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list (8.3.5), cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
No, the virtual keyword on derived classes' virtual function overrides is not required. But it is worth mentioning a related pitfall: a failure to override a virtual function.
The failure to override occurs if you intend to override a virtual function in a derived class, but make an error in the signature so that it declares a new and different virtual function. This function may be an overload of the base class function, or it might differ in name. Whether or not you use the virtual keyword in the derived class function declaration, the compiler would not be able to tell that you intended to override a function from a base class.
This pitfall is, however, thankfully addressed by the C++11 explicit override language feature, which allows the source code to clearly specify that a member function is intended to override a base class function:
struct Base {
virtual void some_func(float);
};
struct Derived : Base {
virtual void some_func(int) override; // ill-formed - doesn't override a base class method
};
The compiler will issue a compile-time error and the programming error will be immediately obvious (perhaps the function in Derived should have taken a float as the argument).
Refer to WP:C++11.
Adding the "virtual" keyword is good practice as it improves readability , but it is not necessary. Functions declared virtual in the base class, and having the same signature in the derived classes are considered "virtual" by default.
There is no difference for the compiler, when you write the virtual in the derived class or omit it.
But you need to look at the base class to get this information. Therfore I would recommend to add the virtual keyword also in the derived class, if you want to show to the human that this function is virtual.
The virtual keyword should be added to functions of a base class to make them overridable. In your example, struct A is the base class. virtual means nothing for using those functions in a derived class. However, it you want your derived class to also be a base class itself, and you want that function to be overridable, then you would have to put the virtual there.
struct B : public A {
virtual void hello() { ... }
};
struct C : public B {
void hello() { ... }
};
Here C inherits from B, so B is not the base class (it is also a derived class), and C is the derived class.
The inheritance diagram looks like this:
A
^
|
B
^
|
C
So you should put the virtual in front of functions inside of potential base classes which may have children. virtual allows your children to override your functions. There is nothing wrong with putting the virtual in front of functions inside of the derived classes, but it is not required. It is recommended though, because if someone would want to inherit from your derived class, they would not be pleased that the method overriding doesn't work as expected.
So put virtual in front of functions in all classes involved in inheritance, unless you know for sure that the class will not have any children who would need to override the functions of the base class. It is good practice.
There's a considerable difference when you have templates and start taking base class(es) as template parameter(s):
struct None {};
template<typename... Interfaces>
struct B : public Interfaces
{
void hello() { ... }
};
struct A {
virtual void hello() = 0;
};
template<typename... Interfaces>
void t_hello(const B<Interfaces...>& b) // different code generated for each set of interfaces (a vtable-based clever compiler might reduce this to 2); both t_hello and b.hello() might be inlined properly
{
b.hello(); // indirect, non-virtual call
}
void hello(const A& a)
{
a.hello(); // Indirect virtual call, inlining is impossible in general
}
int main()
{
B<None> b; // Ok, no vtable generated, empty base class optimization works, sizeof(b) == 1 usually
B<None>* pb = &b;
B<None>& rb = b;
b.hello(); // direct call
pb->hello(); // pb-relative non-virtual call (1 redirection)
rb->hello(); // non-virtual call (1 redirection unless optimized out)
t_hello(b); // works as expected, one redirection
// hello(b); // compile-time error
B<A> ba; // Ok, vtable generated, sizeof(b) >= sizeof(void*)
B<None>* pba = &ba;
B<None>& rba = ba;
ba.hello(); // still can be a direct call, exact type of ba is deducible
pba->hello(); // pba-relative virtual call (usually 3 redirections)
rba->hello(); // rba-relative virtual call (usually 3 redirections unless optimized out to 2)
//t_hello(b); // compile-time error (unless you add support for const A& in t_hello as well)
hello(ba);
}
The fun part of it is that you can now define interface and non-interface functions later to defining classes. That is useful for interworking interfaces between libraries (don't rely on this as a standard design process of a single library). It costs you nothing to allow this for all of your classes - you might even typedef B to something if you'd like.
Note that, if you do this, you might want to declare copy / move constructors as templates, too: allowing to construct from different interfaces allows you to 'cast' between different B<> types.
It's questionable whether you should add support for const A& in t_hello(). The usual reason for this rewrite is to move away from inheritance-based specialization to template-based one, mostly for performance reasons. If you continue to support the old interface, you can hardly detect (or deter from) old usage.
I will certainly include the Virtual keyword for the child class, because
i. Readability.
ii. This child class my be derived further down, you don't want the constructor of the further derived class to call this virtual function.
Why it is not possible to cast something that extends number to number?
Here is simple example in which I'm trying to pass enum as a generic argument to function.
enum Ev {A, B}
function fun<E extends number>(x: {[ix: number]: any}, e: E)
{
return x[<number>e]
}
// no error here, so I assume is true that `Ev extends number`
fun({0:0}, Ev.A)
It seems a bit inconsistent that some type extends number but I get this error when trying to cast it to number:
Neither type 'E' nor type 'number' is assignable to the other.
Edit: Here is almost the same example but with class instead of number (this compiles without error):
class A {}
function fun<E extends A>(x: {[ix: number]: any}, e: E)
{
return x[<A>e]
}
Primitive types cannot be inherited from, as some have special "abilities" that require a special instance, and creating a new derived object would prevent that ability. For instance, there is no way to call the string constructor for a new custom derived object, so no way to apply it to a user instance. This is why nothing inherits from number, or anything else.
Why it is not possible to cast something that extends number to number?
As Ryan has pointed out in this issue, it seems like a bug in the language; however, take note that this form of constraint is only useful when the return type of the function is the constraint on the type parameter. For example:
function f<T extends number>(input: T) : T { return input; }
var t = f(Ev.A); // t : Ev
An issue with the constraint in the function you provided, is that it doesn't prevent passing in a number value. Since it's not possible to constrain to an enum member, you might as well just define your function with the constraint on the parameter instead:
function fun(x: {[ix: number]: any}, e: number)
{
return x[e];
}
A complaint you had with doing this was that it wasn't self documenting code. I would say it's better to give your function a descriptive name that says its intent rather than relying on generics that offer no constraint benefit beyond a number constraint. Also remember that there's no way to force a developer to write the generic part when calling the function. They can easily write fun({0:0}, Ev.A) instead of fun<Ev>({0:0}, Ev.A).
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));
I'm new to the bimap functionality of the Boost libraries, and I'm having trouble passing a bimap into another function. My bimap looks like this:
typedef boost::bimap< int, int > bimap_type;
bimap_type bm;
I have an add_values() function that adds a set of values to the bimap:
add_values(int a, int b)
{
bm.insert(bimap_type::value_type(a, b));
}
I then have a function that is meant to set the values of the bimap by getting them from a Singleton Class:
void set_values()
{
MyClass::instance()->get_values(bm);
}
And, in MyClass, get_values() looks like this:
void get_values(bimap_type myBimap)
{
myBimap.add_values(3, 5);
}
However, MyClass does not recognise 'bimap_type'. I try putting the typedef in a separate header file and including that in MyClass, but I get the error message:
'class bimap_type' has no member named 'add_values'
How can I successfully pass the bimap to this Singleton Class in order to fill it with values from the Class? Does anyone know?
Thanks a lot.
Er, boost::bimap itself doesn't have an add_values method and it's hard to tell from these code fragments why you're suddenly expecting one to appear.
Consider renaming your functions: set_values() that calls get_values() that calls add_values() is one confusing call chain...
When you need to modify an object in a function, you have to take it by reference (or a pointer). The idea is that you must work with the same object inside and outside of the function. If you pass by value, function will see a copy, so anything it does with it does not reflect on original object.
// formerly known as add_values()
void initialize(bimap_type& bm, int a, int b)
{
bm.insert(bimap_type::value_type(a, b));
}
And this is how you will call it:
initialize(myBitmap, 3, 5);
Make sure to update your whole call chain to pass by reference where appropriate, because currently your get_values() works with a copy too.
I get a compilation error
[Error 1 (PE114) Type "array[0..1] of ConsoleApplication.MyEnum" used from type "ConsoleApplication." must be public D:\PrismProjects\ConsoleApplication\ConsoleApplication\Program.pas 14 42 ConsoleApplication]
when I try to compile the following code:
namespace ConsoleApplication;
interface
type
ConsoleApp = class
public
class method Main(args: array of string);
end;
MyEnum = (F, T);
const
EnumOfBool: array[boolean] of MyEnum = [MyEnum.F, MyEnum.T];
implementation
class method ConsoleApp.Main(args: array of string);
begin
Console.WriteLine('Hello World.');
end;
end.
Where is MyEnum defined? I'm pretty sure wherever that is, it is not marked as public (as the error message suggests), but it's left on the default visibility (which is private in .NET).
Then RRUZ is correct in his comment, you should avoid global declarations. The Oxygene compiler needs to create a (invisible, auto-generated) class containing this as a static (class) member anyways because .NET does not allow for global declarations, so you should do it 'right' in the first place.