Why doesn't ths "cross-cast" work?
The following creates this object inheritance model:
FOOD
/ \
CHEESE CAKE
Here I attempt to static_cast a pointer from cheese to cake, making a cheesecake :D. I am getting the following error from Apple Clang/LLVM:
ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed
But they ARE related by inheritance: they are siblings.
Why can't I cast a cheese to a cake, like I cast an int to a float? Why can't I "cross-cast" from derived objects which inherit from the same base class?
Minimal, complete, and verifiable example follows, with static_cast and dynamic_cast attempts included, to highlight errors.
#include <iostream>
#include <string>
class Food {
public:
Food(std::string brand):brand_(brand) {}
virtual ~Food() {};
std::string brand() { return brand_; }
virtual void cut()const { std::cout << "Food cut." << std::endl; }
void eat()const { std::cout << "Food eaten." << std::endl; }
private:
std::string brand_;
};
class Cheese : public Food {
public:
Cheese(std::string brand):Food(brand) {};
virtual void cut()const { std::cout << "Cheese cut.\n"; }
void eat()const { std::cout << "Cheese eaten.\n"; }
};
class Cake : public Food {
public:
Cake(std::string brand):Food(brand) {};
virtual void cut()const { std::cout << "Cake cut.\n"; }
void eat()const { std::cout << "Cake eaten.\n"; }
};
int main() {
Food f("tbd");
Cheese c("Cheddar");
Cake cc("Cheesecake");
Food * food_ptr;
Cheese *cheese_ptr, *cheeseCake_ptr;
Cake *cake_ptr;
food_ptr = &f;
food_ptr->cut(); //-> "Food cut."
food_ptr = &c;
food_ptr->cut(); //-> "Cheese cut." Result of virtual keyword.
cheese_ptr = dynamic_cast<Cheese*> (food_ptr);
cheese_ptr->cut(); //-> "Cheese Cut." The downcast worked
food_ptr = &cc;
cake_ptr = dynamic_cast<Cake*> (food_ptr);
cake_ptr->cut(); //-> "Cake Cut." pointer reassignment and downcast worked.
cheeseCake_ptr = dynamic_cast<Cheese*> (food_ptr);
cheeseCake_ptr->cut(); //-> "Cake cut." Again, Food* dynamically casted to Cheese*
/* ~~~ NOTE: THE FOLLOWING EXAMLES INTENTIONALLY THROW ERRORS ~~~ */
/*
Dynamic cross-cast attempt:
ERROR: Assigning to 'Cheese *' from incompatable type 'Cake *'
Dynamic cast: doensn't make sense, as the relationshiop between cheese and cake is not polymorphic
*/
cheeseCake_ptr = dynamic_cast<Cake*> (cheese_ptr);
cheeseCake_ptr->cut();
/*
Static cross-cast attempt:
ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed
Static cast: why doesn't this work? We know the data types.
*/
cheese_ptr = &c;
cake_ptr = &cc;
cheeseCake_ptr = static_cast<Cake*> (cheese_ptr);
std::cout << "\n\n";
return 0;
}
not related by inheritance would mean on the same branch...
You should not mistake casting values for casting pointers (or the converse), they are different type conversion.
The int to float uses a function to convert a value of a given type to a value of the target type (note that this function can be explicit or implicit, it is implicit for that particular case ie. defined in the langage). In C++ you can implement this on custom class types by implementing a ctor for class A that is able to received a value of type B, or by implementing a cast operator for class B that returns a value of type A.
The Cake * to Cheese * do not convert values, but tries to view a given object in a different manner. It is sub-typing polymorphism (so you need to use dynamic_cast). Given your type hierarchy, a Cheese object can easily be viewed (not converted) as a Food object by using a Food pointer to point to a Cheese object (just like you can be viewed differently by different persons, (think the way friend, professor or doctor can apprehend you while you are always the same person!). It is clear (at least in your hierarchy) that a Cheese can't be viewed as a Cake, if it would be the case how the Cheese object would react to Cake's specific methods? You are an Animal, a Dog also, but it is difficult to imagine that I can view you as a Dog (you don't have 4 legs isn't it?...
Don't be fooled by your case. Ok it seems that the contents of Cheese and Cake are the same, but the given hierarchy tell the truth: there are not on the same branch, you can't get a Cheese pointer from a Cake pointer. C++ compiler protects you against this.
Now things change slightly if you use multiple inheritance like a CheeseCake inheriting from Cheese and Cake. Then given a CheeseCake object viewed through a Cheese pointer, it is possible to convert it to Cake pointer because a CheeseCake is both! Of course even in that multiple inheritance scenario, a Cheese object cannot be viewed as a Cake through pointers.
The error says it all, ERROR: Static cast from 'Cheese *' to 'Cake *', which are not related by inheritance, is not allowed. Even though they are siblings, they are not related through inheritance.
If you absolutely want to make cheesecake, you can do multiple inheritance.
FOOD
/ \
CHEESE CAKE
\ /
CHEESECAKE
Like this:
class CheeseCake : public Cake, public Cheese
Related
Say you have this in an Object-Oriented application:
module Talker
def talk(word)
puts word
end
end
module Swimmer
def swim(distance)
puts "swimming #{distance}"
end
end
class Organism
def initialize
rise
end
def rise
puts "hello world"
end
end
class Animal extends Organism
def think(something)
puts "think #{something}"
end
end
class Bird extends Animal
include Talker
end
class Fish extends Animal
include Swimmer
end
bird = new Bird
fish = new Fish
In this, you can call methods which are unique to each:
bird.talk("hello")
fish.swim(50)
But you can also call methods which are the same:
bird.think("fly")
fish.think("swim")
If I have a function that takes an animal, I can call the think function:
def experience(animal)
animal.think("one")
animal.think("two")
animal.think("one")
end
In a pseudo functional language, you can do the same basically:
function experience(animal) {
think(animal)
think(animal)
think(animal)
}
But not really, you would have to check the type:
function think(genericObject) {
if (genericObject is Animal) {
animalThink(genericObject)
} else if (genericObject is SomethingElse) {
somethingElseThink(genericObject)
}
}
That is because, when implementing your "experience" function, you don't want just animals to experience, you want rocks and trees and other things to experience too, but their experience functions are different.
function experience(thing) {
move(thing)
move(thing)
move(thing)
}
function move(thing) {
case thing {
match Animal then animalMove(thing)
match Plant then plantMove(thing)
match Rock then rockMove(thing)
}
}
In this way, you can't have a cleanly reusable function, your function must know of the specific types it's going to receive somewhere down the line.
Is there any way to avoid this and make it more like OO polymorphism, in a functional language?
If so, at a high level, how does it work under the hood if this can be solved in a functional language?
Achieving polymorphism in functional programming
https://www.quora.com/How-is-polymorphism-used-in-functional-programming-languages
https://wiki.haskell.org/OOP_vs_type_classes
Functional programming languages have a variety of ways of achieving polymorphism. I'm going to contrast Java (the OOP language I know best) with Haskell (the functional language I know best).
Way 1: "parametric polymorphism"
With parametric polymorphism, you don't need to know anything at all about the underlying type. For example, if I have a singly-linked list with elements of type T, I actually don't need to know anything about type T in order to find the length of the list. I would just write something like
length :: forall a . [a] -> Integer
length [] = 0
length (x:xs) = 1 + length xs
in Haskell (obviously I'd want to use a better algorithm in practice, but you get the idea). Note that it doesn't matter what the type of the list elements is; the code for getting the length is the same. The first line is the "type signature". It says that for every type a, length will take a list of a and output an integer.
This can't be used for too much "serious polymorphism", but it's definitely a strong start. It corresponds roughly to Java's generics.
Way 2: typeclass-style polymorphism
Even something as benign as checking for equality actually requires polymorphism. Different types require different code for checking equality, and for some types (generally functions), checking equality is literally impossible because of the halting problem. Thus, we use "type classes".
Let's say I define a new type with 2 elements, Bob and Larry. In Haskell, this looks like
data VeggieTalesStars = Bob | Larry
I would like to be able to compare two elements of type VeggieTalesStars for equality. To do this, I would need to implement an Eq instance.
instance Eq VeggieTalesStars where
Bob == Bob = True
Larry == Larry = True
Bob == Larry = False
Larry == Bob = False
Note that the function (==) has the type signature
(==) :: forall b . Eq b => b -> b -> Bool
This means that for every type b, if b has an Eq instance, then (==) can take two arguments of type b and return a Bool.
It's probably not too difficult for you to guess that the not-equals function (/=) also has the type signature
(/=) :: forall b . Eq b => b -> b -> Bool
Because (/=) is defined by
x /= y = not (x == y)
When we call the (/=) function, the function will deploy the correct version of the (==) function based on the types of the arguments. If the arguments have different types, you won't be able to compare them using (/=).
Typeclass-style polymorphism allows you to do the following:
class Animal b where
think :: b -> String -> String
-- we provide the default implementation
think b string = "think " ++ string
data Fish = Fish
data Bird = Bird
instance Animal Fish where
instance Animal Bird where
Both Fish and Bird implement the "Animal" typeclass, so we can call the think function on both. That is,
>>> think Bird "thought"
"think thought"
>>> think Fish "thought"
"think thought"
This use case corresponds roughly to Java interfaces - types can implement as many type classes as they want. But type classes are far more powerful than interfaces.
Way 3: Functions
If your object only has one method, it may as well just be a function. This is a very common way to avoid inheritance hierarchies - deal with functions rather than inheritors of a 1-method base class.
One might therefore define
type Animal = String -> String
basicAnimal :: Animal
basicAnimal thought = "think " ++ thought
An "animal" is really just a way of taking one string and producing another. This would correspond to the Java code
class Animal {
public String think(String thought) {
return "think " + thought;
}
}
Let's say that in Java, we decided to implement a subclass of animal as follows:
class ThoughtfulPerson extends Animal {
private final String thought;
public ThoughtfulPerson(final String thought) {
this.thought = thought;
}
#Override
public String think(String thought) {
System.out.println("I normally think " + this.thought ", but I'm currently thinking" + thought + ".");
}
}
In Haskell, we would implement this as
thoughtfulPerson :: String -> Animal
thoughtfulPerson originalThought newThought = "I normally think " ++ originalThought ", but I'm currently thinking" ++ newThought ++ "."
The "dependency injection" of Java code is realised by Haskell's higher-order functions.
Way 4: composition over inheritance + functions
Suppose we have an abstract base class Thing with two methods:
abstract class Thing {
public abstract String name();
public abstract void makeLightBlink(int duration);
}
I'm using Java-style syntax, but hopefully it's not too confusing.
Fundamentally, the only way to use this abstract base class is by calling its two methods. Therefore, a Thing should actually be considered to be an ordered pair consisting of a string and a function.
In a functional language like Haskell, we would write
data Thing = Thing { name :: String, makeLightsBlink :: Int -> IO () }
In other words, a "Thing" consists of two parts: a name, which is a string, and a function makeLightsBlink, which takes an Int and outputs an "IO action". This is Haskell's way of dealing with IO - through the type system.
Instead of defining subclasses of Thing, Haskell would just have you define functions which output a Thing (or define Things themselves directly). So if in Java you might define
class ConcreteThing extends Thing {
#Override
public String name() {
return "ConcreteThing";
}
#Override
public void makeLightsBlink(int duration) {
for (int i = 0; i < duration; i++) {
System.out.println("Lights are blinking!");
}
}
}
In Haskell, you would instead define
concreteThing :: Thing
concreteThing = Thing { name = "ConcreteThing", makeLightsBlink = blinkFunction } where
blinkFunction duration = for_ [1..duration] . const $ putStrLn "Lights are blinking!"
No need to do anything fancy. You can implement any behaviour you want by using composition and functions.
Way 5 - avoid polymorphism entirely
This corresponds to the "open vs closed principle" in object oriented programming.
Some times, the correct thing to do is actually to avoid polymorphism entirely. For example, consider how one might implement a singly-linked list in Java.
abstract class List<T> {
public abstract bool is_empty();
public abstract T head();
public abstract List<T> tail();
public int length() {
return empty() ? 0 : 1 + tail().length();
}
}
class EmptyList<T> {
#Override
public bool is_empty() {
return true;
}
#Override
public T head() {
throw new IllegalArgumentException("can't take head of empty list");
}
#Override
public List<T> tail() {
throw new IllegalArgumentException("can't take tail of empty list");
}
}
class NonEmptyList<T> {
private final T head;
private final List<T> tail;
public NonEmptyList(T head, List<T> tail) {
this.head = head;
this.tail = tail;
}
#Override
public bool is_empty() {
return false;
}
#Override
public T head() {
return self.head;
}
#Override
public List<T> tail() {
return self.tail;
}
}
However, this is actually not a good model because you'd like there to only be two ways of constructing a list - the empty way, and the non-empty way. Haskell allows you to do this quite simply. The analogous Haskell code is
data List t = EmptyList | NonEmptyList t (List t)
empty :: List t -> Bool
empty EmptyList = True
empty (NonEmptyList t listT) = False
head :: List t -> t
head EmptyList = error "can't take head of empty list"
head (NonEmptyList t listT) = t
tail :: List t -> List t
tail EmptyList = error "can't take tail of empty list"
tail (NonEmptyList t listT) = listT
length list = if empty list then 0 else 1 + length (tail list)
Of course, in Haskell we try to avoid functions that are "partial" - we try to make sure that every function always returns a value. So you won't see many Haskellers actually using the "head" and "tail" functions for precisely this reason - they sometimes error out. You'd instead see length defined by
length EmptyList = 0
length (NonEmptyList t listT) = 1 + length listT
using pattern-matching.
This feature of functional programming languages is called "algebraic data types". It's incredibly useful.
Hopefully, I've convinced you that not only does functional programming allow you to implement many object-oriented design patterns, it can actually allow you to express the same ideas in much more succinct and obvious forms.
I have added some sugar to your example because it was difficult to justify an object centric implementation with your functions.
Note that I don't write a lot of Haskell but I think it's the right language to draw a comparison.
I don't recommend comparing pure OO languages and pure FP languages directly as it is a waste of time. If you pick up a FP language and learn how to think functionally you will not miss any OO feature.
-- We define and create data of type Fish and Bird
data Fish = Fish String
nemo = Fish "Nemo";
data Bird = Bird String
tweety = Bird "Tweety"
-- We define how they can be displayed with the function `show`
instance Show Fish where
show (Fish name) = name ++ " the fish"
instance Show Bird where
show (Bird name) = name ++ " the bird"
{- We define how animals can think with the function `think`.
Both Fish and Bird will be Animals.
Notice how `show` dispatches to the correct implementation.
We need to add to the type signature the constraint that
animals are showable in order to use `show`.
-}
class Show a => Animal a where
think :: a -> String -> String
think animal thought =
show animal ++ " is thinking about " ++ thought
instance Animal Fish
instance Animal Bird
-- Same thing for Swimmer, only with Fish
class Show s => Swimmer s where
swim :: s -> String -> String
swim swimmer length =
show swimmer ++ " is swimming " ++ length
instance Swimmer Fish
-- Same thing for Singer, only with Bird
class Show s => Singer s where
sing :: s -> String
sing singer = show singer ++ " is singing"
instance Singer Bird
{- We define a function which applies to any animal.
The compiler can figure out that it takes any type
of the class Animal because we are using `think`.
-}
goToCollege animal = think animal "quantum physics"
-- we're printing the values to the console
main = do
-- prints "Nemo the fish is thinking about quantum physics"
print $ goToCollege nemo
-- prints "Nemo the fish is swimming 4 meters"
print $ swim nemo "4 meters"
-- prints "Tweety the bird is thinking about quantum physics"
print $ goToCollege tweety
-- prints "Tweety the bird is singing"
print $ sing tweety
I was wondering what it would look like in Clojure. It's not as satisfying because defprotocol doesn't provide default implementations, but then again: are we not forcing a style upon a language which is not designed for it?
(defprotocol Show
(show [showable]))
(defprotocol Animal
(think [animal thought]))
(defn animal-think [animal thought]
(str (show animal) " is thinking about " thought))
(defprotocol Swimmer
(swim [swimmer length]))
(defprotocol Singer
(sing [singer]))
(defrecord Fish [name]
Show
(show [fish] (str (:name fish) " the fish"))
Animal
(think [a b] (animal-think a b))
Swimmer
(swim [swimmer length] (str (show swimmer) " is swimming " length)))
(defrecord Bird [name]
Show
(show [fish] (str (:name fish) " the bird"))
Animal
(think [a b] (animal-think a b))
Singer
(sing [singer] (str (show singer) " is singing")))
(defn goToCollege [animal]
(think animal "quantum physics"))
(def nemo (Fish. "Nemo"))
(def tweety (Bird. "Tweety"))
(println (goToCollege nemo))
(println (swim nemo "4 meters"))
(println (goToCollege tweety))
(println (sing tweety))
The problem is that what kind of polymorphism you want. If you just need some polymorphism on compile time, Haskell's typeclass is nearly perfect for most situations.
If you want to have polymorphism of run time(i.e. dynamically switch behaviors based on runtime type), this programming pattern is discouraged in many functional programming languages since with powerful generics and typeclasses, dynamic polymorphism is not always necessary.
In short, If the language support subtype, you can choose dynamic polymorphism while in a strict functional language without complete subtypes, you should always program in a functional way. Lastly, If you still want both(dynamic polymorphism and powerful typeclasses), you can try languages with traits like Scala or Rust.
I have this C code:
typedef struct {
double dat[2];
} gsl_complex;
gsl_complex gsl_poly_complex_eval(const double c[], const int len, const gsl_complex z);
The C function returns a whole struct, not just a pointer, so I cannot write the Raku declaration as:
sub gsl_poly_complex_eval(CArray[num64] $c, int32 $len, gsl_complex $z --> gsl_complex)
is native(LIB) is export { * }
Any suggestion?
For that you need a CStruct. The P5localtime module contains a more elaborate example.
The problem
Some C APIs work with structs using a three-phase approach, passing around structs by reference, like this:
struct mystruct *init_mystruct(arguments, ...);
double compute(struct mystruct *);
void clean_mystruct(struct mystruct *);
This way the implementation hides the data structure, but this comes with a price: the final users have to keep track of their pointers and remember to clean up after themselves, or the program will leak memory.
Another approach is the one that the library I was interfacing used: return the data on the stack, so it can be assigned to an auto variable and automatically discarded when it goes out of scope.
In this case the API is modeled as a two-phase operation:
struct mystruct init_mystruct(arguments, ...);
double compute(struct mystruct);
The structure is passed on the stack, by value and there's no need to clean up afterwards.
But Raku's NativeCall interface is only able to use C structs passing them by reference, hence the problem.
The solution
This is not a clean solution, because it steps back into the first approach described, the three-phase one, but it's the only one I have been able to devise so far.
Here I consider two C functions from the library's API: the first creates a complex number as a struct, the second adds up two numbers.
First I wrote a tiny C code interface, the file complex.c:
#include <gsl/gsl_complex.h>
#include <gsl/gsl_complex_math.h>
#include <stdlib.h>
gsl_complex *alloc_gsl_complex(void)
{
gsl_complex *c = malloc(sizeof(gsl_complex));
return c;
}
void free_gsl_complex(gsl_complex *c)
{
free(c);
}
void mgsl_complex_rect(double x, double y, gsl_complex *res)
{
gsl_complex ret = gsl_complex_rect(x, y);
*res = ret;
}
void mgsl_complex_add(gsl_complex *a, gsl_complex *b, gsl_complex *res)
{
*res = gsl_complex_add(*a, *b);
}
I compiled it this way:
gcc -c -fPIC complex.c
gcc -shared -o libcomplex.so complex.o -lgsl
Note the final -lgsl used to link the libgsl C library I am interfacing to.
Then I wrote the Raku low-level interface:
#!/usr/bin/env raku
use NativeCall;
constant LIB = ('/mydir/libcomplex.so');
class gsl_complex is repr('CStruct') {
HAS num64 #.dat[2] is CArray;
}
sub mgsl_complex_rect(num64 $x, num64 $y, gsl_complex $c) is native(LIB) { * }
sub mgsl_complex_add(gsl_complex $a, gsl_complex $b, gsl_complex $res) is native(LIB) { * }
sub alloc_gsl_complex(--> gsl_complex) is native(LIB) { * }
sub free_gsl_complex(gsl_complex $c) is native(LIB) { * }
my gsl_complex $c1 = alloc_gsl_complex;
mgsl_complex_rect(1e0, 2e0, $c1);
say "{$c1.dat[0], $c1.dat[1]}"; # output: 1 2
my gsl_complex $c2 = alloc_gsl_complex;
mgsl_complex_rect(1e0, 2e0, $c2);
say "{$c2.dat[0], $c2.dat[1]}"; # output: 1 2
my gsl_complex $res = alloc_gsl_complex;
mgsl_complex_add($c1, $c2, $res);
say "{$res.dat[0], $res.dat[1]}"; # output: 2 4
free_gsl_complex($c1);
free_gsl_complex($c2);
free_gsl_complex($res);
Note that I had to free explicitly the three data structures I created, spoiling the original C API careful design.
I have 2 enums.
typedef enum {
BLUE = 1,
RED = 2
} FavoriteColor;
typedef enum {
ORANGE = 1,
YELLOW = 2,
RED = 3
} Color;
In my code how can I refer to a specific RED from FavoriteColor enum, but not Color enum?
You can't. And the compiler should warn you about that.
enum constants live in the global namespace. The second definition is a redefinition that should produce an error.
It is not possible to have scoped enumerations. The general way around this is to use prefixes which appear in most libraries like UIKit. You should define your enumerations like this:
typedef enum {
FavoriteColorBlue = 1,
FavoriteColorRed= 2
} FavoriteColor;
typedef enum {
ColorOrange = 1,
ColorYellow = 2,
ColorRed= 3
} Color;
The only other way would be to use a class with static access to constants as described here.
use enum class instead just enum. Then you can use the same names for different enums;
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
using namespace std;
enum class window {large,small};
enum class box {large,small};
int main()
{
window mywindow;
box mybox;
mywindow = window::small;
mybox = box::small;
if (mywindow == window::small)
cout << "mywindow is small" << endl;
if (mybox == box::small)
cout << "mybox is small" << endl;
mybox = box::large;
if (mybox != box::small)
cout << "mybox is not small" << endl;
cout << endl;
}
I have a situation in Objective-C where a Java-style enum would be very helpful. I have a set of layer types, and each layer has its own persistence value associated with it (stored in seconds). I want to keep these layer types in an enum, since they're too similar to make into separate classes, like so:
typedef enum {
ExplosionLayerType,
FireworkLayerType,
FireLayerType,
FireJetLayerType
} FXLayerType;
In Java, I could easily associate these two values with something like this:
public enum FXLayerType {
Explosion(3),
Firework(6),
Fire(7),
FireJet(-1);
private int persistence;
FXLayerType(int persistence) {
this.persistence = persistence;
}
}
Is there a simple way to create a sort of lightweight class like this in Objective-C, or will need to resort to more primitive methods?
EDIT:
Various people have suggested doing something like this:
typedef enum {
ExplosionLayerType = 3,
FireworkLayerType = 6
} FXLayerType;
This will not work for me, since I may have something like this (Java-style enum):
Explosion(3),
Firework(6),
Dust(3);
In Java, Dust and Explosion will be treated as unique values, but direct assignment with C enums will treat them as being exactly the same.
If you just want a primitive container for type and value, consider this approach:
typedef struct FXLayerValue {
FXLayerType type;
int value;
} FXLayerValue;
Then again, a class hierarchy may be worth consideration if things become complex or are better handled dynamically. Caveat: if you have a ton of objects to save and/or create, an objc type will be overkill and degrade performance.
Unfortunately, my Java-Fu isn't good enough to know all the lang differences for enums.
To emulate Java enum's we need something which is comparable (can be operands of == etc.), which can have fields, and is lightweight. This suggests structs, and optionally pointers to structs. Here is an example of the latter:
FXLayerType.h:
typedef const struct { int persistence; } FXLayerType;
extern FXLayerType * const LayerTypeExplosion;
extern FXLayerType * const LayerTypeFirework;
extern FXLayerType * const LayerTypeDust;
FXLayerType.m:
#import "FXLayerType.h"
const FXLayerType _LayerTypeExplosion = { 3 };
const FXLayerType _LayerTypeFirework = { 6 };
const FXLayerType _LayerTypeDust = { 3 };
FXLayerType * const LayerTypeExplosion = &_LayerTypeExplosion;
FXLayerType * const LayerTypeFirework = &_LayerTypeFirework;
FXLayerType * const LayerTypeDust = &_LayerTypeDust;
So FXLayerType itself is a constant struct, while as with Obj-C objects we always use pointers to these structs. The implementation creates 3 constant structs and 3 constant pointers to them.
We can now write code such as:
FXLayerType *a, *b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(#"%d, %d\n", a == b, a->persistence == b->persistence);
Which will output "0, 1" - a and b are different enums (0) but have the same persistence (1). Note here a and b are not constant pointers, only the enum "literals" are defined as constants.
As written this has the disadvantage that you cannot switch on an enum value. However if that is needed just add a second field, say tag, and init it with a unique value using a real enum, say FXLayerStyleTag. You can also remove the indirection if you are happy to always compare tags (e.g. a.tag ==b.tag`). This gives you:
FXLayerType.h:
typedef enum { ExplosionTag, FireworkTag, DustTag } FXLayerTypeTag;
typedef struct { FXLayerTypeTag tag; int persistence; } FXLayerType;
extern const FXLayerType LayerTypeExplosion;
extern const FXLayerType LayerTypeFirework;
extern const FXLayerType LayerTypeDust;
FXLayerType.m:
#import "FXLayerType.h"
const FXLayerType LayerTypeExplosion = { ExplosionTag, 3 };
const FXLayerType LayerTypeFirework = { FireworkTag, 6 };
const FXLayerType LayerTypeDust = { DustTag, 3 };
Use:
FXLayerType a, b;
a = LayerTypeDust;
b = LayerTypeExplosion;
NSLog(#"%d, %d\n", a.tag == b.tag, a.persistence == b.persistence);
A difference between the two designs is the first passes around pointers while the second structures, which may be larger. You can combine them, to get switchable pointer-based enums - that is left as an exercise!
Both these designs also have the (dis)advantage that the number of enum "literals" can be extended at any time.
Actually you may assign values to the enum keys in C, as they are nothing but ints:
typedef enum {
LayerTypeExplosion = 3,
LayerTypeFirework = 6,
LayerTypeFire = 7,
LayerTypeFireJet = -1
} FXLayerType;
You may use them then simply as a restricted set of values, to be assigned to a variable of type FXLayerType.
FXLayerType myLayerType = LayerTypeFirework;
NSLog(#"Value of myLayerType = %i", myLayerType);
// => "Value of myLayerType = 6"
This is not 100% equivalent, but this might be an approach you could take in Objective-C. Basically, create several class-level convenience methods to construction the various configuration of FXLayerType.
#interface FXLayerType
{
#private
int persistence;
}
+ (FXLayerType*)fireworkLayerType;
+ (FXLayerType*)explosionLayerType;
+ (FXLayerType*)jetLayerType;
#end
#implementation FXLayerType
+ (FXLayerType*)explosionLayerTypeWithPersistence:(int)persistence
{
FXLayerType* layerType = [[FXLayerType new] autorelease];
layerType->persistence = persistence;
return layerType;
}
+ (FXLayerType*)explosionLayerType
{
return [self explosionLayerTypeWithPersistence:3];
}
+ (FXLayerType*)fireworkLayerType
{
return [self explosionLayerTypeWithPersistence:6];
}
+ (FXLayerType*)jetLayerType
{
return [self explosionLayerTypeWithPersistence:-1];
}
#end
Usage:
FXLayerType* aJetLayerType = [FXLayerType jetLayerType];
I have recently used the j2objc format for enums. It works rather nicely. Additionally you can auto generate your enums if you are trying to map directly from a java object.
https://code.google.com/p/j2objc/wiki/Enums
However, I did remove the j2objc specific classes from my "Enums". I did not want the additional dependencies.
The struct based answers look good on their face but fail when you try to add Objective-C objects into the struct. Given that limitation, truly emulating the Java-style enum may be more work than it is worth.
I've got a series of OpenCv generated YAML files and would like to parse them with yaml-cpp
I'm doing okay on simple stuff, but the matrix representation is proving difficult.
# Center of table
tableCenter: !!opencv-matrix
rows: 1
cols: 2
dt: f
data: [ 240, 240]
This should map into the vector
240
240
with type float. My code looks like:
#include "yaml.h"
#include <fstream>
#include <string>
struct Matrix {
int x;
};
void operator >> (const YAML::Node& node, Matrix& matrix) {
unsigned rows;
node["rows"] >> rows;
}
int main()
{
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
Matrix m;
doc["tableCenter"] >> m;
return 0;
}
But I get
terminate called after throwing an instance of 'YAML::BadDereference'
what(): yaml-cpp: error at line 0, column 0: bad dereference
Abort trap
I searched around for some documentation for yaml-cpp, but there doesn't seem to be any, aside from a short introductory example on parsing and emitting. Unfortunately, neither of these two help in this particular circumstance.
As I understand, the !! indicate that this is a user-defined type, but I don't see with yaml-cpp how to parse that.
You have to tell yaml-cpp how to parse this type. Since C++ isn't dynamically typed, it can't detect what data type you want and create it from scratch - you have to tell it directly. Tagging a node is really only for yourself, not for the parser (it'll just faithfully store it for you).
I'm not really sure how an OpenCV matrix is stored, but if it's something like this:
class Matrix {
public:
Matrix(unsigned r, unsigned c, const std::vector<float>& d): rows(r), cols(c), data(d) { /* init */ }
Matrix(const Matrix&) { /* copy */ }
~Matrix() { /* delete */ }
Matrix& operator = (const Matrix&) { /* assign */ }
private:
unsigned rows, cols;
std::vector<float> data;
};
then you can write something like
void operator >> (const YAML::Node& node, Matrix& matrix) {
unsigned rows, cols;
std::vector<float> data;
node["rows"] >> rows;
node["cols"] >> cols;
node["data"] >> data;
matrix = Matrix(rows, cols, data);
}
Edit It appears that you're ok up until here; but you're missing the step where the parser loads the information into the YAML::Node. Instead, se it like:
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc); // <-- this line was missing!
Matrix m;
doc["tableCenter"] >> m;
Note: I'm guessing dt: f means "data type is float". If that's the case, it'll really depend on how the Matrix class handles this. If you have a different class for each data type (or a templated class), you'll have to read that field first, and then choose which type to instantiate. (If you know it'll always be float, that'll make your life easier, of course.)