Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic template with member function pointer as parameter

I've watched several examples online and I don't understand why this doesn't compile.. what I'm trying to do is passed a member function of say class Object, to a class that has a vector of said Objects, and have a function with templated arguments as parameters be called... example:

template <typename ...Args_t>
bool objectsDo(bool (Object::*func)(Args_t...), Args_t&&... args) {
    for (int i = 0 ; i < OBJECTS ; ++i) {
        if (!m_objects[i]->*func(std::forward<Args_t>(args)...)) {
            return false;
        }
    }
    return true;
}

but every function I try, even a parameterless one I get:

error: no instance of function template "objectsDo" matches the argument list
            argument types are: (bool ())
                objectsDo(&Object::close);

where my usage is:

            objectsDo(&Object::close);

EDIT: as suggested by Columbo, I am now sending the address to the function, but still I get errors when sending with parameters, such as :

  error: no instance of function template "objectsDo" matches the argument list
            argument types are: (bool (Object::*)(int, char), int, char)
like image 839
Alon Avatar asked Nov 09 '14 11:11

Alon


People also ask

How to declare pointer to member function c++?

The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object. Because the precedence of () (function call operator) is higher than . * and ->* , you must use parentheses to call the function pointed to by ptf .

What is Variadic template in C++?

A variadic template is a class or function template that supports an arbitrary number of arguments. This mechanism is especially useful to C++ library developers: You can apply it to both class templates and function templates, and thereby provide a wide range of type-safe and non-trivial functionality and flexibility.

How to instantiate template function?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>(float original); Template arguments may be omitted when the compiler can infer them.

What is special about Variadic functions?

Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.


1 Answers

I assume you call the function like this:

int main()
{
    int i; char c;
    objectsDo(&Object::close, i, c);
}

The problem is that the template arguments are deduced inconsequently:

template <typename ...Args_t>
bool objectsDo(bool (Object::*func)(Args_t...), Args_t&&... args)

Args_t is deduced as int, char for the first parameter and int&, char& for the second. That is because of the internal working of universal references: It works with reference collapsing.

Use another parameter-pack for the trailing parameters :

template <typename ...Args_t, typename... Args>
bool objectsDo(bool (Object::*func)(Args_t...), Args&&... args)
{ /* […] */ }

Or make the trailing parameter a non-deduced context:

template <typename T> struct identity {using type = T;};
template <typename T>
using identity_t = typename identity<T>::type;

template <typename ...Args_t>
bool objectsDo(bool (Object::*func)(Args_t...), identity_t<Args_t>... args){
    // […]
}
like image 100
Columbo Avatar answered Sep 19 '22 10:09

Columbo