Pass generic type in C ++ method as parameter

I am trying to implement a C ++ method and want to pass a generic parameter to it. I only want to assign this parameter to an object property. Here's an example:

class Myclass {
public:
    unsigned long long var1;
    unsigned short var2;
    signed short var3; 
}

      

Now I have a global Myclass object in SomeOtherClass and the method says:

void SomeOtherClass::updateMyClassValue(int paramType, <Generic> value) {
     switch(paramType) {
         case1:
          objMyClass.var1 = value;
         case2:
          objMyClass.var2 = value;
         case3:
          objMyClass.var3 = value;
     }
} 

      

How can I pass a type like this, because if I use a fixed type unsigned long long

as the parameter type, I cannot assign it to var2 and var3. I also don't want to lose data, for example signed data might be -ve.

Please help me to overcome this situation, I have no experience in C ++. I'm not sure if I can achieve this using templete <> in C ++, if so how?

thank

+4


source to share


6 answers


Pass the parameter by pointer:

void SomeOtherClass::updateMyClassValue(int paramType, void* pValue) {
 switch(paramType) {
     case1:
      objMyClass.var1 = *(unsigned long long*)pValue;
     case2:
      objMyClass.var2 = *(unsigned short)pValue;
     case3:
      objMyClass.var3 = *(signed short)pValue;
 }

      

This is of course not type safe and you can run into big problems when you accidentally specify the wrong paramType. If you are using a member template function instead, you can let the compiler do some checking for you, for example:



template<type T>
void SomeOtherClass::updateMyClassValue<short int>(T value) {
    objMyClass.var2 = value;
}

      

More elegant and safer type.

+2


source


One way to do it is function overloading:

template <class T>
void updateMyClassValue(T value) {
    //assert, or log message, or nothing, if not needed you can remove this function
}

void updateMyClassValue(unsigned long long value) {
    var1 = value;
}

void updateMyClassValue(unsigned short value) {
    var2 = value;
}

void updateMyClassValue(signed short value) {
    var3 = value;
}

      



Another approach is the boost :: any type .

+1


source


The best way is to overload the function for the types that need updating. This will be resolved at compile time and you can save a few loops and lines of code for switch/case

. For unwanted types, you might have a function private

.

Below is one way to avoid duplicate code:

#define UPDATE(VAR) VAR; \  
public: void updateMyClassValue (const decltype(VAR)& value) { VAR = value; }

class Myclass {
public:
    unsigned long long UPDATE(var1);
    unsigned short UPDATE(var2);
    signed short UPDATE(var3); 

private: template<typename T> void updateMyClassValue (T);
};

      

Demo version which also includes error script.

+1


source


I think you could do it with templates. For example:

#include <iostream>

using namespace std;

class Myclass {
public:
    unsigned long long var1;
    unsigned short var2;
    signed short var3;
};

class SomeOtherClass
{

public:

    Myclass objMyClass;

    template <typename T>
    void updateMyClassValue(int paramType, T value);


};




template <typename T>
void SomeOtherClass::updateMyClassValue(int paramType, T value) {

    switch(paramType) {
        case 1:
            objMyClass.var1 = value;
        case 2:
            objMyClass.var2 = value;
        case 3:
            objMyClass.var3 = value;
    }
}

int main() {


    SomeOtherClass soc;


    unsigned long long var1 = 11;
    unsigned short var2     = 22;
    signed short var3       = 33;

    soc.updateMyClassValue(1, var1);
    soc.updateMyClassValue(2, var2);
    soc.updateMyClassValue(3, var3);

    cout << soc.objMyClass.var1 << endl;
    cout << soc.objMyClass.var2 << endl;
    cout << soc.objMyClass.var3 << endl;

    return 0;
}

      

Output:

11
22
33

      

0


source


There are several ways to do what you want as other answers suggest: template method, pointers, overloaded method, generic types such as boost::any

.

But before choosing one, look at your problem from a design perspective. You have a class with three member variables of different types. What do they mean, what do they represent? Are they different representations of the same class attribute, or are they completely different attributes of that class (think of the class from an OO point of view, not just a simple C ++ syntax)?

Case 1 - different ways to represent the same value

In this case, consider storing the value in one form in the class and converting it to other forms on demand.

For example: you are developing a class Temperature

that can keep the temperature in Celsius or Fahrenheit. Instead of having members for storing temperature in each of the two formats, you only need to have one and convert it to another format if necessary.

class Temperature
{
public:
    void setCelsius(double degrees)
    {
        celsiusTemperature = degrees;
    }

    void setFahrenheit(double degrees)
    {
        celsiusTemperature = (degrees - 32) * 5.0 / 9.0;
    }

    double getCelsius() const
    {
        return celsiusTemperature;
    }

    double getFahrenheit() const
    {
        return celsiusTemperature * 9.0 / 5.0 + 32;
    }

private:
    double celsiusTemperature;
}

      

Case 2 - different class values ​​/ attributes

If variables contain different class attributes and mean different things, then they have different methods for setting them, not a common method for setting each one. The variable should be named and printed according to its purpose and the value of the value it stores. The setter for a variable should be named and printed according to the same principles.

eg.

class Person
{
public:
private:
    string name;
    int age;
    double height;
}

      

In this case, it would be more obvious to have a general method

void setPersonAttribute(int attributeType, T value);

      

or have a method for each attribute

void setName(string name);
void setAge(int age);
void setHeight(double height);

      

0


source


I'm not sure if this is relevant to your problem, since you need base types. But I noticed that nobody mentioned the following:

I. Mechanism of inheritance:

class BaseType;

class Var1 : public BaseType
{};
class Var2 : public BaseType
{};
class Var3 : public BaseType
{};

class Myclass
{
public:
    Var1 m_var1;
    Var2 m_var2;
    Var3 m_var3;
};

void SomeOtherClass::updateMyClassValue(int paramType, BaseType value) {
     switch(paramType) {
         case1:
          objMyClass.m_var1 = value;
         case2:
          objMyClass.m_var2 = value;
         case3:
          objMyClass.m_var3 = value;
     }
} 

      

Of course there is no type checking, etc., but this is a valid option, checked at compile time .

II. Callback mechanism:

Again, I think this might be too complicated for your problem, but you can also pass a callback function to set a specific element value and value.

0


source







All Articles