2

I have this simple C++ template function. I need to pass any number of arguments of any type to the Method, as shown below. How do I do this?

template <typename T1, typename T2, auto Method>
T1 * wrapObject()
{
    T2 * obj = (*_asposeObj.*Method)(// I would like to pass arguments here);
    ...
}

This is a C++20 project, compiler is g++.

I tried:

template <typename T1, typename T2, auto Method, auto ...Args>
T1 * wrapObject(Args... args)
{
    T2 * obj = (*_asposeObj.*Method)(&args);
    ...
}

But this won't compile. Any ideas?

EDIT:

Thanks for all the help, it works now!

However, there is another related problem: What if there are two versions of Method in asposeObj? Like:

asposeObj->idx_get(int index);
asposeObj->idx_get(someObj);

The compiler doesn't seem to be able to figure our which one to call and I'm getting "unable to deduce ‘auto’ from ..." errors.

How to modify the following call to make this work? wrapObject is the template function I mentioned above.

wrapObject<SomeClass, AnotherClass, &ClassAsposeOj::idx_get>(index)
user2297996
  • 1,382
  • 3
  • 18
  • 28

2 Answers2

8

It may be that you are not using the parameter pack in the correct way.

Correct usage:

template <typename T1, typename T2, auto Method, class ...Args>
T1 * wrapObject(Args &&... args)
{
    T2 * obj = (*_asposeObj.*Method)(args...);
    ...
}

With perfect forwarding:

template <typename T1, typename T2, auto Method, class ...Args>
T1 * wrapObject(Args &&... args)
{
    T2 * obj = (*_asposeObj.*Method)(std::forward<Args>(args)...);
    ...
}

Learn more: What are the main purposes of using std::forward and which problems it solves?

Sprite
  • 3,222
  • 1
  • 12
  • 29
2

You can use std::invoke to simplify calling syntax:

template<typename T1, typename T2, auto Method, typename... Args>
T1* wrapObject(Args... args) {
    // ...
    T2* obj = std::invoke(Method, _asposeObj, args...);  // std::forward, if needed
}

The second argument of std::invoke is the object you're calling Method on. It can be a pointer or a reference, std::invoke will do the right thing automagically.

Simple demo

Evg
  • 25,259
  • 5
  • 41
  • 83