In templates as shown below, I would like the call Run(&Base::foo)
succeed without the need to name the Base type twice (as is done in the compiling Run<Base>(&Base::foo)
call). Can I have that? Possibly without adding a ton of Boost headers?
With the provided code, I get an error of:
prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’
(you can fiddle with the snippet at http://ideone.com/8NZkq):
#include <iostream>
class Base {
public:
bool foo() { return true; }
};
Base* x;
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
T* y = dynamic_cast<T*>(x);
std::cout << (y->*check)();
}
int main() {
Base y;
x = &y;
Run<Base>(&Base::foo);
Run(&Base::foo); // why error?
}
The
T
inTraits<T>::BoolMethodPtr
is in a non-deduced context, so the compiler will not deduce automatically from the call what type T should be. This is because there could be code like this:If you can do without the
Traits<T>
class, you can writeRun
as:In this context,
Class
can be deduced to meanBase
To pick apart a type, any type, use partial specialization. There is no function template partial specialization, so you'll need to directly parameterize the function on its argument type and retrieve the class type inside.
When the compiler tries to match a template argument, it only considers the primary class type. In other words, when it encounters the expression:
...and it's trying to figure out the template parameter for
Run
, it only considers the type offoo
itself, and doesn't consider whatever classfoo
is a part of.EDIT:
And the type of
foo
isbool(Base::*)(void)
, but what you want the compiler to find is justBase
I think this is a non deduced context.
I think this is the quote that applies in this case. But some template gods need to ratify my understanding.