I am trying to override the default value of enum passed as a parameter, but I am getting the default value.
class MyClass
{
public:
enum MyCalculation
{
SUM,
DIVIDE,
MULTIPLY,
NOCALCULATION
};
void foo(MyCalculation cal = NOCALCULATION);
void DoCalculation();
};
void MyClass::DoCalculation()
{
MyCalculation cal;
// here I am getting the enum value at runtime
int val = // get enum value
switch(val)
{
case 0:
cal = MyClass::SUM;
break;
case 1:
cal = MyClass::DIVIDE;
break;
case 2:
cal = MyClass::MULTIPLY;
break;
}
foo(cal);
}
void MyClass::foo(MyCalculation getCal)
{
cout << getCal;
}
I tried passing by reference in DoCalculation method, but I am always getting NOCALCULATION in foo.
Do I need to do something else?
Related
Is there a way to convert a string to an enum in vala:
string foo = "Enum1";
MY_ENUM theEnum = MY_ENUM.get_value_by_name(foo);
enum MY_ENUM {
Enum1,
Enum2,
Enum3
}
So in this example "theEnum" would have the value: MY_ENUM.Enum1
It is possible using the runtime type system provided by GLib's GObject library. There are EnumClass and EnumValue. These provide introspection at runtime and allow an enum to be initialised from a string.
The syntax is a bit complex at present, although it may be possible for someone to modify the Vala compiler to make it easier, but that is a significant piece of work.
An example:
void main () {
try {
MyEnum? the_enum_value;
the_enum_value = MyEnum.parse ("FIRST");
print (#"$(the_enum_value)\n");
} catch (EnumError error) {
print (#"$(error.message)\n");
}
}
errordomain EnumError {
UNKNOWN_VALUE
}
enum MyEnum {
FIRST,
SECOND,
THIRD;
public static MyEnum parse (string value) throws EnumError {
EnumValue? a;
a = ((EnumClass)typeof (MyEnum).class_ref ()).get_value_by_name ("MY_ENUM_" + value);
if (a == null) {
throw new EnumError.UNKNOWN_VALUE (#"String $(value) is not a valid value for $(typeof(MyEnum).name())");
}
return (MyEnum)a.value;
}
}
I want to mock a function which has a pointer argument
class I_Shaft
{
public:
virtual ~I_Shaft() {
}
virtual void GetFloor(I_Floor* FloorPointer) = 0;
};
the mocked interface:
class Mock_I_Shaft : public I_Shaft
{
public:
MOCK_METHOD1(GetFloor, void(I_Floor* FloorPointer));
};
the mocked interface Mock_I_Floor which needs a default and a copy constructor (otherwise it won't get compiled):
class Mock_I_Floor : public I_Floor
{
public:
Mock_I_Floor() {}
Mock_I_Floor(const Mock_I_Floor& f) {}
virtual ~Mock_I_Floor() {};
MOCK_METHOD0(GetPosition, uint16_t());
};
the implementation that is to be tested:
C_HZS::C_HZS(I_Shaft& refShaft) : //constructor initializing refShaft
refShaft(refShaft)
{
}
void C_HZS::run(void)
{
I_Floor* ptrFloor = NULL;
refShaft.GetFloor(ptrFloor);
if(ptrFloor == NULL){
std::cerr << "there is no valid pointer" <<std::endl;
return;
}
floorPosition = ptrFloor->GetPosition();
std::cout << "floorPosition: " << floorPosition << std::endl;
}
and here is my test:
TEST(HZS, testFloorPosition) {
Mock_I_Shaft shaft;
Mock_I_Floor floor;
Mock_I_Floor* pFloorMocked= &floor;
C_HZS dutObj(shaft);
EXPECT_CALL(shaft, GetFloor(_))
.Times(AtLeast(1))
.WillOnce(SetArgPointee<0>(*pFloorMocked)
);
dutObj.run();
EXPECT_FALSE(...);
}
The problem is: I am not able to inject pFloorMocked into the mocked function. Within the run() function ptrFloor always stays NULL. What is the reason for this? Is there another way to mock this function?
I want to know weather is is possible or not, a way to call different classes on the basis of an integer value without conditional statements like switch case?
What I am having is:
int val = // getting some value here from a method
String data = // getting some value here from a method
switch(val)
{
case 1:
{
new TempClass1(data);
break;
}
case 2:
{
new TempClass2(data);
break;
}
}
What I want is like:
int val = // getting some value here from a method
String data = // getting some value here from a method
new TempClass(val, data);
This should call the object of TempClass1 or TempClass1 as per "val"
Any help will be appreciated.
Maybe use a Factory for the classes, assuming your two classes share a base class named TempBaseClass:
class TempClassFactory {
static public TempBaseClass getTempClass(int val, String data)
{
switch(val)
{
case 1:
{
return new TempClass1(data);
break;
}
case 2:
{
return new TempClass2(data);
break;
}
default:
throw new Exception("Bad value");
}
}
}
int val = // getting some value here from a method
String data = // getting some value here from a method
TempClassFactory::getTempClass(val, data);
So lets say I have this enum
public enum StatType
{
Strength, Dexterity, Intelligence, Wisdom, Luck
}
and I have this function,
public void SetStats(StatType type, int value)
{
switch (type)
{
case StatType.Strength:
hero.Stats.Strength += value;
break;
case StatType.Dexterity:
hero.Stats.Dexterity += value;
break;
case StatType.Intelligence:
hero.Stats.Intelligence += value;
break;
case StatType.Wisdom:
hero.Stats.Wisdom += value;
break;
case StatType.Luck:
hero.Stats.Luck += value;
break;
}
}
How can I change this incoming stat's "type" parameter to hero.Stats.( ) variable's name?
If this is possible, then I don't need to use switch, right?
I have the following code which copies property values from one object to another objects by matching their property names:
public static void CopyProperties(object source, object target,bool caseSenstive=true)
{
PropertyInfo[] targetProperties = target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] sourceProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo tp in targetProperties)
{
var sourceProperty = sourceProperties.FirstOrDefault(p => p.Name == tp.Name);
if (sourceProperty == null && !caseSenstive)
{
sourceProperty = sourceProperties.FirstOrDefault(p => p.Name.ToUpper() == tp.Name.ToUpper());
}
// If source doesn't have this property, go for next one.
if(sourceProperty ==null)
{
continue;
}
// If target property is not writable then we can not set it;
// If source property is not readable then cannot check it's value
if (!tp.CanWrite || !sourceProperty.CanRead)
{
continue;
}
MethodInfo mget = sourceProperty.GetGetMethod(false);
MethodInfo mset = tp.GetSetMethod(false);
// Get and set methods have to be public
if (mget == null)
{
continue;
}
if (mset == null)
{
continue;
}
var sourcevalue = sourceProperty.GetValue(source, null);
tp.SetValue(target, sourcevalue, null);
}
}
This is working well when the type of properties on target and source are the same. But when there is a need for casting, the code doesn't work.
For example, I have the following object:
class MyDateTime
{
public static implicit operator DateTime?(MyDateTime myDateTime)
{
return myDateTime.DateTime;
}
public static implicit operator DateTime(MyDateTime myDateTime)
{
if (myDateTime.DateTime.HasValue)
{
return myDateTime.DateTime.Value;
}
else
{
return System.DateTime.MinValue;
}
}
public static implicit operator MyDateTime(DateTime? dateTime)
{
return FromDateTime(dateTime);
}
public static implicit operator MyDateTime(DateTime dateTime)
{
return FromDateTime(dateTime);
}
}
If I do the following, the implicit cast is called and everything works well:
MyDateTime x= DateTime.Now;
But when I have a two objects that one of them has a DateTime and the other has MyDateTime, and I am using the above code to copy properties from one object to other, it doesn't and generate an error saying that DateTime can not converted to MyTimeDate.
How can I fix this problem?
One ghastly approach which should work is to mix dynamic and reflection:
private static T ConvertValue<T>(dynamic value)
{
return value; // This will perform conversion automatically
}
Then:
var sourceValue = sourceProperty.GetValue(source, null);
if (sourceProperty.PropertyType != tp.PropertyType)
{
var method = typeof(PropertyCopier).GetMethod("ConvertValue",
BindingFlags.Static | BindingFlags.NonPublic);
method = method.MakeGenericMethod(new[] { tp.PropertyType };
sourceValue = method.Invoke(null, new[] { sourceValue });
}
tp.SetValue(target, sourceValue, null);
We need to use reflection to invoke the generic method with the right type argument, but dynamic typing will use the right conversion operator for you.
Oh, and one final request: please don't include my name anywhere near this code, whether it's in comments, commit logs. Aargh.