

C++:类型擦除
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.

记录一下模板类型擦除
#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
Recommend
-
30
你可能听过这个术语 : 类型擦除 。甚至你也用过标准库中的类型擦除(AnySequence)。但是具体什么是类型擦除, 我们怎么才能实现类型擦除呢?这篇文章就是介绍这件事情的。 在日常的开发中, 总有想要把某个类或...
-
33
0.8552019.06.10 00:21:08字数 921阅读 1,339
-
15
↑ 点击 蓝字 关注极市平台 作者丨皮特...
-
9
浅谈泛型擦除2021-07-01 • Otstar Lin • 泛型是 Java 5 引入的一个新特性,现在的高级语言基本也都支持泛型了。泛型本质上是将类型作为参数,以提供类型检查和避免不必要的类型转换。具体关于类型的本篇文章就不再说明了,具体...
-
8
Swift 基于闭包的类型擦除 Original...
-
7
颜色擦除强度干涉仪实现高空间分辨成像 来源:《中国科学报》2021-09-06 1...
-
6
Swift 类型擦除 发表于 2021-10-10 ...
-
5
4 个用来擦除数据的 Linux 工具 | Linux 中国用这些开源工具从你的硬盘驱动器中擦除数据。来源:https://linux.cn/article-...
-
2
编辑导语:人们有时会有一些不想被他人发现的联系记录,针对这个需求,华为手机上有一个擦除联系痕迹的功能。这篇文章对此功能从需求、设计逻辑以及宏观角度进行了深度分析,希望对你有所帮助。
-
7
Swift 风味各异的类型擦除-51CTO.COM Swift 风味各异的类型擦除 作者:Swift君 2022-03-31 09:01:10 一开始,“类型擦除”一词似乎与 Swift 给我们的关注类型和编译时类型安全性的第一感觉相反,因...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK