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)
1 Answer 1
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){
// [...]
}
&beforeObject::close