Home > Blockchain >  How to implement a template provding different values for different tyes
How to implement a template provding different values for different tyes

Time:06-08

I am using a library which define various constants, like JQX_TYPE_INT, JQX_TYPE_LONG, JQX_TYPE_DOUBLE etc.

My problem is to relate values to c types.

For example, in order to have a function which works for various types i have to implement a copy of the same code, differing only in the constant, for every c -type, e.g.:

myObj *createObject(int iSize, int iDummy) {
    int iRealSize = calcEffectiveSize(iSize, JQX_TYPE_INT);
    return new myObj(iRealSize);
}  

myObj *createObject(int iSize, double dDummy) {
    int iRealSize = calcEffectiveSize(iSize, JQX_TYPE_DOUBLE);
    return new myObj(iRealSize);
}  

// ... same for float char, etc.

That is, apart from having to implement the same code several times, i have to use a dummy variable in order to use the constant related to the c -type.

Is there some sort of template approach to do something like

template<tyepename T>
struct jqx_type {
     static const int type;
     // ... template magic
}  


template<<typename T>
myObj *createObject(int iSize) {
    int iRealSize = calcEffectiveSize(iSize, jqx_type<T>::type);
    return new myObj(iRealSize);
}  

I tried this

template<typename T>
struct jqx_type {
    static const int type = JQX_TYPE_NONE;
};

template<typename T=int>
struct jqx_type {
    static const int type = JQX_TYPE_INT;
};

template<typename T=long>
class jqx_types {
    static const int type = JQX_TYPE_LONG;
};

But this doesn't even compile.

Is there a way to achieve what i intend to do?

CodePudding user response:

Here:

template<typename T>
struct jqx_type {
    static const int type = JQX_TYPE_NONE;
};

template<typename T=int>
struct jqx_type {
    static const int type = JQX_TYPE_INT;
};

template<typename T=long>
class jqx_types {
    static const int type = JQX_TYPE_LONG;
};

You redeclared the same template several times with different default arguments. What you actually want is one template with different specializations:

template<typename T>
struct jqx_type {
    static const int type = JQX_TYPE_NONE;
};

template<>
struct jqx_type<int> {
    static const int type = JQX_TYPE_INT;
};

template<>
struct jqx_types<long> {
    static const int type = JQX_TYPE_LONG;
};

PS: type is very common name for member type aliases. I would not use it for an int. Maybe type_selector is a better name.

CodePudding user response:

I would go with a much simpler

myObj *createObject(int iSize, int jqx_type) {
    return new myObj(calcEffectiveSize(iSize, jqx_type));
}

myObj *o = createObject(16, JQX_TYPE_DOUBLE);

or if it needs to be constexpr

template <int jqx_type>
myObj *createObject(int iSize) {
    return new myObj(calcEffectiveSize(iSize, jqx_type));
}

myObj *o = createObject<JQX_TYPE_DOUBLE>(16);

but lets assume you need the actual type it could be something like this:

template <typename T>
struct MyObj {
  MyObj(std::size_t size, int jqx_type)
      : iSize{calcEffectiveSize(size, jqx_type)} { ... }
  MyObj * create(std::size_t size) {
      constexpr int jqx_type = []() {
          if constexpr (std::is_same_v<T, int>) return JQX_TYPE_INT;
          if constexpr (std::is_same_v<T, double>) return JQX_TYPE_DOUBLE;
      }();
      return new MyObj{iSize, jqx_type};
  }
};

or if you do want to go the type traits route then you have to specialize the template struct like this:

template<typename T>
struct jqx_type {
    static const int type = JQX_TYPE_NONE;
};

template<>
struct jqx_type<int> {
    static const int type = JQX_TYPE_INT;
};

template<>
struct jqx_types<long> {
    static const int type = JQX_TYPE_LONG;
};

But that's as much code as specializing the createObject function.

PS: you can match and mix ideas, too. E.g. template createObject function with the if constexpr lambda.

  • Related