Gyulaxxx
Gyulaxxx

Reputation: 11

Use template functions inside template

I want to implement the following for more than one (i.e. many) functions (function1(), function2(), ...etc.).

Currently I have it separately as follows:

template <typename T>
concept iterator_1 = requires(T const& t) {
  t.function1();
};
template <iterator_1 R>
static float getterFunction(R const& r)
{
  return r.function1();
}
template <typename T>
concept iterator_2 = requires(T const& t) {
  t.function2();
};
template <iterator_2 R>
static float getterFunction(R const& r)
{
  return r.function2();
}

I want to use a general getterFunction to choose function1(), function2(), ...etc. with an if condition, such as follows:

template <typename A>
float getterFunction(A const& a)
{
  auto i = -1;
  if (something==0) {
    i = a.function1();
  } 
  else if (something==1) {
    i = a.function2();
  }
  else if {
    ...
  }
  return i;
}

I would like to use this general getterFunction as follows:

template <typename B> 
void DoSomething(typename B::iterator const& b)
{
  float value = getterFunction(b);
  ...
}

I was wondering if there is a more general way of doing this, instead of writing many concepts for each of the many functions?

Upvotes: 1

Views: 47

Answers (1)

Dominik Kaszewski
Dominik Kaszewski

Reputation: 545

Since concepts are checked at compile time, you could use if constexpr which discards any non-taken branch:

template <typename A>
auto getterFunction(A const& a)
{
    if constexpr (iterator_1<A>) {
        return a.function1();
    } else if constexpr (iterator_2<A>) {
        return a.function2();
    } else {
        static_assert(false);
    } 
}

}

You may want to consider adding a check that only one concept is satisfied, as any type which satisfies more will just use the first one in the checked order. static_assert(std::ranges::count({ iterator_1<A>, iterator_2<A>... }, true) == 1); should do the trick.

Upvotes: 1

Related Questions