I was toying around with function pointers to non-static methods and stumbled upon some GCC-messages that don't quite make sense to me. Let's maybe look at some code:
#include<iostream>
struct X{ int print() const { std::cout << "hello"; return 0; } };
struct Y: public X{};
template<class T>
struct print_one
{
const T& t;
print_one(const T& _t): t(_t) {}
template<class Something>
void _call(Something (T::*fct)() const) const
{
std::cout << (t.*fct)() << '\n';
}
void do_print() const { _call(&T::print); }
};
int main()
{
X x;
Y y;
print_one<X>(x).do_print();
//print_one<Y>(y).do_print();
}
I was ready to see this fail because I thought the return value of a method does not contribute to its "ID" so to say. However, this compiles (gcc-9 --std=c++17) and works fine.
But, if I instanciate print_one with a Y (uncomment last line in main()) things go south:
test_ptr.cpp: In instantiation of 'void print_one<T>::do_print() const [with T = Y]':
test_ptr.cpp:28:28: required from here
test_ptr.cpp:19:27: error: no matching function for call to 'print_one<Y>::_call(int (X::*)() const) const'
19 | void do_print() const { _call(&T::print); }
| ^~~~~
test_ptr.cpp:14:8: note: candidate: 'template<class Something> void print_one<T>::_call(Something (T::*)() const) const [with Something = Something; T = Y]'
14 | void _call(Something (T::*fct)() const) const
| ^~~~~
test_ptr.cpp:14:8: note: template argument deduction/substitution failed:
test_ptr.cpp:19:27: note: mismatched types 'const Y' and 'const X'
19 | void do_print() const { _call(&T::print); }
| ^~~~~
In particular with Something = Something seems weird to me. Further, the whole thing works if I explicitly give the template instanciation like so: _call<int>(&T::print).
So, the questions would be: why can GCC deduce the template argument Something although it's not part of the signature of the print method and why does the deduction fail when confronted with a class derived from the class defining the actual method?
Aucun commentaire:
Enregistrer un commentaire