Lukin
Lukin

Reputation: 63

C++ member function template using template

Sorry for confused title. I don't know how else to say it. Example should explain itself.

I found something called typemaps and use it to my code like this:

template<typename T>
struct typemap
{
    static const int INDEX;
};

template<>
const int typemap<Type1>::INDEX = 1;
template<>
const int typemap<Type2>::INDEX = 3;
template<>
const int typemap<Type3>::INDEX = 11;

Type1 Type2 & Type3 are stucts and used like type in here. The INDEX number cannot be inside the struct because there could be another typemap with different numbers but with the same type-object. So the typemap works for different order of the stucts in colection like vector, because the order matter to me.

Next thing is non-template class which has Type1-3 as attributes. And what I'm trying to do is to insert these attributes into vector, that is done with help of std::function. But I need to take general typemap and use it as index to insert to vector.

The only thing i thought it may work is using more templates. Something like the next code, but this is not correct way and since I'm still new to templates I need help to write it correctly so the body of function toVector start working as i need.

class MyClass
{
  Type1 type1_;
  Type2 type2_;
  Type3 type3_;
  ..

  template<typename T>
  void toVector(T& typemap)
  {
    std::vector<..> vect;
    vect.resize(..);
    vect[typemap<Type1>::INDEX] = type1_.someFunction(..);
    vect[typemap<Type2>::INDEX] = type2_.someFunction(..);
  }

};

I'm sure i use the template wrong with the member function, i somehow need to say that T parameter also have some template parameter. Sorry for my english, not native speaker. Also sorry for the ".." It's unrelated to my problem and it would mess the code.

Upvotes: 3

Views: 226

Answers (2)

Barry
Barry

Reputation: 302663

Instead of adding explicit specializations for INDEX, let's create an actual object type typemap which you can pass around. First some boilerplate:

template <class T>
struct tag_type {
    using type = T;
};

template <class T>
constexpr tag_type<T> tag{};

template <int I>
using int_ = std::integral_constant<int, I>;

Now, we create an object with a bunch of overloads for index() which take different tag_types and return different int_s.:

struct typemap {
    constexpr int_<3> size() const { return {}; }

    constexpr int_<1> index(tag_type<Type1> ) const { return {}; }
    constexpr int_<3> index(tag_type<Type2> ) const { return {}; }
    constexpr int_<11> index(tag_type<Type3> ) const { return {}; }
};

which is something that you can pass in to a function template and just use:

  template<typename T>
  ??? toVector(T const& typemap)
  {
      std::vector<..> vect;
      vect.resize(typemap.size());

      vect[typemap.index(tag<Type1>)] = ...;
      vect[typemap.index(tag<Type2>)] = ...;
      vect[typemap.index(tag<Type3>)] = ...;
  }

Upvotes: 2

bfair
bfair

Reputation: 1111

Barry's answer is a better way to do what you are trying to do, but here is the answer to your specific question regarding having a template parameter that is itself a template taking one parameter:

  template<template<typename> class type_with_one_template_parameter>
  void toVector()
  {
    std::vector<..> vect;
    vect.resize(..);
    vect[type_with_one_template_parameter<Type1>::INDEX] = type1_.someFunction(..);
    vect[type_with_one_template_parameter<Type2>::INDEX] = type2_.someFunction(..);
  }

It wasn't clear why the function had the T& typemap parameter in your original example, so I've removed it.

Upvotes: 2

Related Questions