All the time, I find myself doing something like this:
Animal *animal = ...
if (Cat *cat = dynamic_cast(animal)) {
...
}
else if (Dog *dog =
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 struct remove_class { };
template
struct remove_class { using type = R(A...); };
template
struct remove_class { using type = R(A...); };
template
struct remove_class { using type = R(A...); };
template
struct remove_class { using type = R(A...); };
template
struct get_signature_impl { using type = typename remove_class<
decltype(&std::remove_reference::type::operator())>::type; };
template
struct get_signature_impl { using type = R(A...); };
template
struct get_signature_impl { using type = R(A...); };
template
struct get_signature_impl { using type = R(A...); };
template using get_signature = typename get_signature_impl::type;
// End ecatmur's code
// Begin typecase code
template
void typecase(
Base *base,
FirstSubclass &&first,
RestOfSubclasses &&... rest) {
using Signature = get_signature;
using Function = std::function;
if (typecaseHelper(base, (Function)first)) {
return;
}
else {
typecase(base, rest...);
}
}
template
void typecase(Base *) {
assert(false);
}
template
bool typecaseHelper(Base *base, std::function func) {
if (T *first = dynamic_cast(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!