3

How can a static constexpr class::method (int i1, int i2, int i3) be invoked, having input data available as tuple<int, int, int> in a constexpr way.

The default approach is using std::apply to apply each tuple element as argument to a function.

A minimal example to visualize, what I try to achieve looks like:

struct a {
    template <typename T>
    static constexpr void test(int i1, int i2, int i3) {
        // ...
    }
};

struct b : a {};
struct c {};

template <typename T>
struct test_functor {
    constexpr test_functor_t() {} // just for testing to express constexpr desire
    constexpr void operator()(auto... args) {
        T::test<c>(args...);
    }
};

constexpr std::tuple<int, int, int> tupl{ 1,2,3 };
constexpr test_functor<b> f;
std::apply(f, tupl);

this works at runtime, but fails to compile constexpr. How can this be implemented?

Chris G.
  • 816
  • 2
  • 15

1 Answers1

5

Working test_functor:

template <typename T>
struct test_functor {
    constexpr void operator()(auto... args) const {
        T::template test<c>(args...);
    }
};

The problems:

  1. Your constructor was misnamed, and ultimately unnecessary – without a constructor your type is an aggregate and can be constexpr-constructed just fine.
  2. Your operator() was not const – the primary problem, as you can't invoke a non-const member on a constexpr object.
  3. Missing template keyword when invoking T::test – see this FAQ answer for a good explanation of dependent names.

Online Demo

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • Thanks for pointing out the missing ```template``` keyword too. To improve 3. further, it should be ```T::template test(std::forward(args)...);```. – Chris G. Apr 24 '22 at 18:28
  • 1
    @Chris : Indeed, but only if you also change `args` into a pack of forwarding references; otherwise that `std::forward` is really a misleading/confusing `std::move`. ;-] – ildjarn Apr 24 '22 at 18:36