3

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.

4
  • 1
    You're looking for template template parameters. Commented May 17, 2016 at 14:58
  • 1
    When people get rid of bad habit of naming constants UPPERCASE? Commented May 17, 2016 at 14:58
  • 2
    @Slava why is it a bad habit? Commented May 17, 2016 at 14:59
  • 1
    @ChrisG constants in C++ are used to be a preprocesor macro, preprocessor macros are uppercase to avoid naming collisions. This habit grows from there. Constants are not macro anymore and it is better not to use uppercase for exactly the same reason. Commented May 17, 2016 at 15:02

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

3

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

4 Comments

I'm not really familiar with constexpr, but shouldn't it be <class T> constexpr tag_type<T> tag(){}; ? Btw. thx for this way of solution, I'll try it, it really looks interesting, but as I see I still need to learn a lot, some of the code structures used here are new to me.
@Lukin No - what would the extra parentheses be there for?
it won't compile without it, im on g++ -std=c++11 not sure if that's the problem, i got error: template declaration of ‘constexpr const tag_type<T> tag’
@Lukin Variable templates are a C++14 feature. With C++11, you'll have to substitute where I use tag<T> to explicitly write tag_type<T>{}.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.