2

C++:类型擦除

 2 years ago
source link: https://www.lpime.cn/article/124
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C++类型擦除

记录一下模板类型擦除

#pragma once

#include <iostream>
using namespace std;

template<typename R, typename... Args>
class FunctorBridge {
public:

    virtual ~FunctorBridge() = default;

    virtual FunctorBridge* clone() const = 0;

    virtual R invoke(Args... args) = 0;

    virtual R invoke(Args... args) const = 0;
};


template<typename Functor, typename R, typename... Args>
class SpecificFunctorBridge : public FunctorBridge<R, Args...> {
    Functor functor;
public:
    template<typename FunctorFwd>
    explicit SpecificFunctorBridge(FunctorFwd&& functor)
        : functor(std::forward<FunctorFwd>(functor)) {}

    virtual SpecificFunctorBridge* clone() const override {
        return new SpecificFunctorBridge(functor);
    }

    virtual ~SpecificFunctorBridge() {
        std::cout << "~SpecificFunctorBridge" << std::endl;
    }

    R invoke(Args ... args)  override {
        return functor(std::forward<Args>(std::forward<Args>(args))...);
    }

    R invoke(Args ... args) const override {

        return functor(std::forward<Args>(std::forward<Args>(args))...);
    }
};


//声明
template<typename Signature>
class FunctionPtr;

//特化
template<typename R, typename ...Args>
class FunctionPtr<R(Args...)> {
private:
    FunctorBridge<R, Args...>* bridge;
public:
    FunctionPtr() : bridge(nullptr) {}

    ~FunctionPtr() {
        std::cout << "~FunctionPtr" << std::endl;
        if (bridge) {
            delete bridge;
            bridge = nullptr;
        }
    }

    template<typename F>
    FunctionPtr(F&& f) {
        using Functor = decay_t<F>;
        using Bridge = SpecificFunctorBridge<Functor, R, Args...>;
        bridge = new Bridge(forward<F>(f));
    }

    R operator()(Args...args) {
        return bridge->invoke(std::forward<Args>(args)...);
    }
};

class AA {
private:
    int xx;
public:
    void operator()(int x) {
        xx++;
        cout << "A::operator()()" << endl;
    }

    void operator()(int x) const {
        cout << "A::operator()() const" << endl;
    }

    ~AA() {
        std::cout << "~AA" << std::endl;
    }
};

void pr(int x) {
    cout << "pr" << endl;
}

int main()
{
    // lamda
    FunctionPtr<void(int)> xx([](int b) {
        cout << "hello world" << b << endl;
        });
    xx(12);

    //函数指针
    FunctionPtr<void(int)> xy(pr);
    xy(12);

    //函数对象
    //AA a{};
    FunctionPtr<void(int)> xz(AA{});
    xz(12);
    return 0;
}

----

//**https://zhuanlan.zhihu.com/p/351291649**

#pragma once
#include <iostream>

using namespace std;

struct task_base {
    virtual ~task_base() {}
    virtual void operator()() const = 0;
};


template <typename F>
struct task_model : public task_base
{
    F functor_;

    template <typename U> //构造函数是函数模板
    task_model(U&& f) : functor_(std::forward<U>(f)) {}

    void operator()() const override 
    {
        functor_();
    }
};

class my_task;

//C++20以下
//template <typename F>
//using is_not_my_task = std::enable_if_t<
//    !std::is_same_v< std::remove_cvref_t<F>, my_task >,
//    int>;
//
//template <
//    typename F,
//    is_not_my_task<F> = 0>
//my_task(F&& f);

template <typename F>
concept is_not_my_task = !std::is_same_v<std::remove_cvref_t<F>, my_task>;

class my_task {
    std::unique_ptr<task_base> ptr_;

public:

    template <typename F>
    requires is_not_my_task<F>
    my_task(F&& f)
    {
        using F_decay = std::decay_t<F>;   //类型退化,函数可以赋值成函数指针
        using model_type = task_model<F_decay>;
        ptr_ = std::make_unique<model_type>(std::forward<F_decay>(f));
    }

    void operator()() const 
    {
        ptr_->operator()();
    }

    // 其他部分略
     // 移动构造函数
    my_task(my_task&& oth) noexcept : ptr_(std::move(oth.ptr_))
    {}

    // 移动赋值函数
    my_task& operator=(my_task&& rhs) noexcept 
    {
        ptr_ = std::move(rhs.ptr_);
        return *this;
    }

    // 析构函数
    ~my_task() = default;

    // 删除复制构造函数、复制赋值函数
    my_task(const my_task&) = delete;
    my_task& operator=(const my_task&) = delete;
};

// 普通函数
void foo() 
{
    std::cout << "type erasure 1" << std::endl;
}

// 重载括号运算符的类
struct foo2 
{
    void operator()() const
    {
        std::cout << "type erasure 2" << std::endl;
    }
};

#include <fstream>
#include <string>

int main()
{
    task_model<decltype(&foo)> t7{ &foo };

    my_task t1{ &foo };
    t1(); // 输出"type erasure 1"

    my_task t4{ foo };
    t4();

    my_task t2{ foo2{} };
    t2(); // 输出"type erasure 2"

    // Lambda
    my_task t3{
        []() { std::cout << "type erasure 3" << std::endl; }
    };
    t3(); // 输出"type erasure 3"

    my_task t5{
        []() { std::cout << "type erasure"; }
    };

    //无法调用复制构造函数,这里会调用构造函数,加上限制,会禁止调用
    //my_task t6{ t5};
      return 0;
} 

本文由 Ryan 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: 2022/08/20 16:41


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK