Thanks to an answer from ecatmur at https://stackoverflow.com/a/13359520 I was able to extract the signature from the lambda. The full solution looks like this:
// Begin ecatmur's code
template<typename T> struct remove_class { };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
template<typename T>
struct get_signature_impl { using type = typename remove_class<
decltype(&std::remove_reference<T>::type::operator())>::type; };
template<typename R, typename... A>
struct get_signature_impl<R(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(&)(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(*)(A...)> { using type = R(A...); };
template<typename T> using get_signature = typename get_signature_impl<T>::type;
// End ecatmur's code
// Begin typecase code
template<typename Base, typename FirstSubclass, typename... RestOfSubclasses>
void typecase(
Base *base,
FirstSubclass &&first,
RestOfSubclasses &&... rest) {
using Signature = get_signature<FirstSubclass>;
using Function = std::function<Signature>;
if (typecaseHelper(base, (Function)first)) {
return;
}
else {
typecase(base, rest...);
}
}
template<typename Base>
void typecase(Base *) {
assert(false);
}
template<typename Base, typename T>
bool typecaseHelper(Base *base, std::function<void(T *)> func) {
if (T *first = dynamic_cast<T *>(base)) {
func(first);
return true;
}
else {
return false;
}
}
// End typecase code
and an example usage is here:
class MyBaseClass {
public:
virtual ~MyBaseClass() { }
};
class MyDerivedA : public MyBaseClass { };
class MyDerivedB : public MyBaseClass { };
int main() {
MyBaseClass *basePtr = new MyDerivedB();
typecase(basePtr,
[](MyDerivedA *a) {
std::cout << "is type A!" << std::endl;
},
[](MyDerivedB *b) {
std::cout << "is type B!" << std::endl;
});
return 0;
}
If anyone has any improvements, please tell me!
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…