sh1
sh1

Reputation: 4751

Template parameter pack can't infer `const&` argument

So I have a class:

struct C {
  int x[10];

  int const& get(int i) const { return x[i]; }

  template<typename... Ts>
  auto& get(Ts... args) {
    int const& (C::*f)(Ts...) const = &C::get;
    return const_cast<int&>((this->*f)(args...));
  }
};

and the template will generate a non-const getter on demand, so this becomes legal:

int& test(C& c) {
  int i = 4;
  int& r = c.get(i);
  return r;
}

but if I change the original getter's argument type to a reference:

  int const& get(int const& i) const { return x[i]; }

the non-const getter template can't match the const getter anymore.

Obviously it's no big deal passing an int by value, and it's no big deal passing the argument list explicitly to the template, but I have more complex arguments and numerous overloads, and I'd like to infer all my non-const getters with a minimum of copy-paste.

Is there any way past this?


One thought I had was that I could declare the problem argument list within the class but leave the definition to the template, so that the argument matching would have some guidance. I tried adding the following to the class (either before or after the template):

  int& get(int const& i);

Unfortunately this bypasses the template altogether and results in a link error. Adding inline or template to the declaration didn't seem to do the trick either.

Upvotes: 1

Views: 226

Answers (1)

Leon
Leon

Reputation: 32484

Why do you enforce the call to a const member function through an auxiliary pointer to member-function? In such cases I use const qualification of this:

template<typename... Ts>
auto& get(Ts... args) {
    const C* const const_this = this;
    return const_cast<int&>(const_this->get(args...));
}

Upvotes: 2

Related Questions