Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ templates working with objects *and* pointers

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading