• <li id="00i08"><input id="00i08"></input></li>
  • <sup id="00i08"><tbody id="00i08"></tbody></sup>
    <abbr id="00i08"></abbr>
  • 新聞中心

    EEPW首頁 > 嵌入式系統 > 設計應用 > 解說C++ 的類型擦除:std::function 和std::any

    解說C++ 的類型擦除:std::function 和std::any

    作者:嵌入式經驗分享 時間:2025-08-04 來源:今日頭條 收藏

    編程中,我們經常會遇到需要編寫獨立于其操作類型(包括不同函數類型和變量類型)的情況(類似于C語言中的回調函數,但是能適配任意類型)。這時, (Type Erasure) 就派上用場了,它讓我們能夠以統一的方式處理各種類型。本文將探討的定義、工作原理,并提供實現 std::function 和 std::any 的示例。

    什么是

    類型擦除是一種無需繼承或模板即可實現多態性的語言規范。它隱藏了對象的具體類型,只暴露一個統一的接口。這使我們能夠通過一個通用接口存儲、傳遞和操作不同類型的對象,而無需在編譯時知道具體類型。

    為什么使用類型擦除

    類型擦除有幾個主要優點:

    靈活性:你可以通過一個接口處理不同類型的對象。

    解耦:使用類型擦除對象的代碼在編譯時無需知道具體類型。

    多態性:無需繼承即可實現運行時的多態性,從而更容易地處理不共享公共基類的現有類型。

    實現類型擦除:std::function 和 std::any

    標準庫提供了 std::function 和 std::any,它們是類型擦除的示例。一起看看它們的工作原理。

    簡化的 std::function

    std::function 是一個多功能的可調用對象包裝器。它可以存儲函數、lambda 表達式或定義了()運算操作符的對象。std::function 的關鍵特性在于它隱藏了可調用對象的類型,從而統一了調用接口。

    示例:

    #include <iostream>#include <memory>#include <utility>class CallableBase { //沒有類型的接口類public:    virtual ~CallableBase() = default;    virtual void call() const = 0; //純虛函數};template <typename T>  //用這個子類對接口類重載,賦值具體類型的函數class CallableWrapper : public CallableBase{public:
       CallableWrapper(T callable) :callable_(std::move(callable)) {}    void call() const override {
           callable_();
    }private:
       T callable_;
    };class SimpleFunction{public:template <typename T>
    SimpleFunction(T callable): //創建時賦值初始化
    callableImpl_(std::make_shared<CallableWrapper<T>>(std::move(callable))) {}void operand() const {//()操作符
       if(callableImpl_)
        callableImpl_->call();
    }private:    std::shared_ptr<CallableBase> callableImpl_; //無類型的接口變量};void helloFunction(){    std::cout <<"Hello, function !!! n";
    }int main(){
       SimpleFunction f1 = helloFunction;
       SimpleFunction f2 = [](){std::cout << "Hello, Lambda !!!n";};
       f1(); //輸出:Hello, Function !!!
       f2(); //輸出:Hello, Lambda !!!
       return 0;
    }

    在此例中,SimpleFunction 用于存儲常規函數和lambda 表達式。被調用函數的實際類型被擦除了,并且 SimpleFunction 提供了一種統一的方法來調用存儲的函數。

    簡化的 std::any

    std::any 是一個類型安全的容器,可容納任何類型的單個值。它可以存儲任何類型的對象,并且可以使用類型安全的強制類型轉換來檢索存儲的值。

    #include <iostream>
    #include <memory>
    #include <utility>
    #include <typeinfo>
    #include <typeindex>class AnyBase{public:
       virtual ~AnyBase() = default;
       virtual std::type_index type() const = 0;
       virtual std::unique_ptr<AnyBase> clone() = 0;
    };

    template <typename T>class AnyWrapper : public AnyBase{public:
       explicit AnyWrapper(T value) : value_(std::move(value)){}
       std::type_index type() const override { //存儲了類型信息,類型轉換時用
           return typeid(T);
       }

       std::unique_ptr<AnyBase> clone() override{        return std::make_unique<AnyWrapper<T>>(value_);
       }
       T& get(){        return value_;
       }

    private:
       T value_;
    };class SimpleAny{public:
       SimpleAny() = default;

       template <typename T>
       SimpleAny(T value)
           : value_(std::make_unique<AnyWrapper<T>>(std::move(value))){}

       SimpleAny(const SimpleAny& other)
           : value_(other.value_ ? other.value_->clone() : nullptr){}
       
       SimpleAny& operator=(const SimpleAny& other) {        if (this != &other) {
               value_ = other.value_ ? other.value_->clone() : nullptr;
           }        return *this;
       }

       std::type_index type() const{        return value_ ? value_->type() : typeid(void);
       }

       template <typename T>
       T& get(){        if (type() != typeid(T)) { //類型轉換時判斷是否類型匹配
               throw std::bad_cast();
           }        return static_cast<AnyWrapper<T>*>(value_.get())->get();
       }private:
       std::unique_ptr<AnyBase> value_;
    };

    int main(){
       SimpleAny a(10);
       std::cout << "Stored int: " << a.get<int>() << "n";

       a = std::string("Hello, Any!");
       std::cout << "Stored string: " << a.get<std::string>() << "n";    return 0;
    }

    本例中,“SimpleAny”用于存儲一個 int 類型,然后存儲一個 std::string 類型。


    關鍵詞: C++ 類型擦除

    評論


    技術專區

    關閉
    主站蜘蛛池模板: 彰武县| 芜湖县| 客服| 秦皇岛市| 绥江县| 沂源县| 正镶白旗| 罗源县| 汕尾市| 商洛市| 北辰区| 介休市| 冷水江市| 诏安县| 云南省| 桃园市| 商丘市| 衡水市| 南丹县| 阳城县| 仙桃市| 巨鹿县| 花垣县| 云林县| 宜春市| 大埔区| 凤庆县| 北海市| 高陵县| 十堰市| 麻城市| 望城县| 木里| 绍兴县| 保定市| 图木舒克市| 会泽县| 东港市| 上杭县| 婺源县| 龙南县|