“类型开关"在 C++11 中构造

2023-10-18C/C++开发问题
2

本文介绍了“类型开关"在 C++11 中构造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

一直以来,我发现自己在做这样的事情:

All the time, I find myself doing something like this:

Animal *animal = ...
if (Cat *cat = dynamic_cast<Cat *>(animal)) {
    ...
}
else if (Dog *dog = dynamic_cast<Dog *>(animal)) {
    ...
}
else { assert(false); }

当我看到 C++11 中的闭包时,我想知道这样的事情可能吗?

Once I see closures in C++11, I wonder, is something like this possible?

Animal *animal = ...
typecase(animal,
    [](Cat *cat) {
        ...
    },
    [](Dog *dog) {
        ...
    });

实现 typecase 应该很容易,但我一直遇到一个问题,它无法找出函数的参数,所以它不知道尝试 dynamic_cast 到什么,因为很难推断 lambdas 的参数.用了几天的时间在 google 和 SO 上搜索,但终于弄明白了,所以我将在下面分享我的答案.

Implementing typecase should have been easy, but I keep running into a problem where it can't figure out the function's argument, so it can't know what to try to dynamic_cast to, because it's hard to deduce lambdas' parameters. Took a few days of searching google and SO, but finally figured it out, so I'll share my answer below.

推荐答案

感谢 ecatmur 在 https://stackoverflow.com/上的回答a/13359520 我能够从 lambda 中提取签名.完整的解决方案如下所示:

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

示例用法如下:

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!

这篇关于“类型开关"在 C++11 中构造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

无法访问 C++ std::set 中对象的非常量成员函数
Unable to access non-const member functions of objects in C++ std::set(无法访问 C++ std::set 中对象的非常量成员函数)...
2024-08-14 C/C++开发问题
17

从 lambda 构造 std::function 参数
Constructing std::function argument from lambda(从 lambda 构造 std::function 参数)...
2024-08-14 C/C++开发问题
25

STL BigInt 类实现
STL BigInt class implementation(STL BigInt 类实现)...
2024-08-14 C/C++开发问题
3

使用 std::atomic 和 std::condition_variable 同步不可靠
Sync is unreliable using std::atomic and std::condition_variable(使用 std::atomic 和 std::condition_variable 同步不可靠)...
2024-08-14 C/C++开发问题
17

在 STL 中将列表元素移动到末尾
Move list element to the end in STL(在 STL 中将列表元素移动到末尾)...
2024-08-14 C/C++开发问题
9

为什么禁止对存储在 STL 容器中的类重载 operator&amp;()?
Why is overloading operatoramp;() prohibited for classes stored in STL containers?(为什么禁止对存储在 STL 容器中的类重载 operatoramp;()?)...
2024-08-14 C/C++开发问题
6