记录一下模板类型擦除
#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