简体   繁体   中英

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.

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_type s 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>)] = ...;
  }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM