I want to make a function template that will work with object instances and pointers as well. This is important to me as this is the first step towards implementing a function that operates on a vector of elements as well as a vector of pointers to elements.
Here my code so far
#include <functional>
#include <iostream>
struct Foo
{
int num_ = 42;
void print_num() const { std::cout << num_ << std::endl; }
};
template<typename T> void print_num(const T & obj)
{
std::invoke(&T::print_num, obj);
}
template<typename T> void print_num_ptr(const T * const obj)
{
std::invoke(&T::print_num, obj);
}
int main(int argc, char * argv[])
{
Foo foo;
Foo * foo_ptr = &foo;
print_num(foo); // works
print_num_ptr(foo_ptr); // works
print_num(foo_ptr); // doesn't compile
return 0;
}
And this is the compilation error I get
foo.cpp:14:18: error: type 'Foo *' cannot be used prior to '::' because it has no members
std::invoke(&T::print_num, obj);
^
foo.cpp:30:5: note: in instantiation of function template specialization 'print_num<Foo *>' requested here
print_num(foo_ptr); // doesn't work
^
1 error generated.
make[2]: *** [CMakeFiles/foo.dir/foo.cpp.o] Error 1
make[1]: *** [CMakeFiles/foo.dir/all] Error 2
make: *** [all] Error 2
Any ideas?
Thanks. Cheers
=========
❯❯ g++ --version
Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Target: x86_64-apple-darwin22.6.0
Thread model: posix
Remove the pointer-ness from the type using std::remove_pointer_t
:
std::invoke(&std::remove_pointer_t<T>::print_num, obj);
If T
isn't a pointer, remove_pointer_t
will return the same type unchanged.
Or, if your only goal is to support Foo::print_num()
, not ??::print_num()
in general, you can just use &Foo::print_num
.