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?

3
  • 1
    Please provide a minimal reproducible example. Commented Apr 24, 2022 at 17:46
  • 1
    std::apply is constexpr. If the function you want to call is constexpr, what's the issue? Commented Apr 24, 2022 at 17:54
  • @NicolBolas the missing const declaration of operator() was the issue as ildjarn pointed out in 2. Commented Apr 24, 2022 at 18:25

1 Answer 1

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

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

2 Comments

Thanks for pointing out the missing template keyword too. To improve 3. further, it should be T::template test<c>(std::forward<decltype(args)>(args)...);.
@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. ;-]

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.