gpt4 book ai didi

c++ - 什么是C++运行时概念?

转载 作者:行者123 更新时间:2023-12-01 19:46:47 27 4
gpt4 key购买 nike

最近,我一直在网上寻找有关C++概念的详细信息,并且找到了对几篇论文称为“run-time concepts”的引用。它们与编译时概念有何不同?为什么首先引入它们,如何实现它们?它们为什么对C++的 future 很重要?通过浏览这些论文,我得到了一个一般性的想法,即运行时概念旨在缓解当前面向对象的代码与通用代码之间的当前紧张关系,但是我从中没有得到太多帮助。

最佳答案

这是我对正在发生的事情的理解。它从另一个角度开始:类型擦除。
std::function<void()>是类型擦除类的示例。它采用了“无参数调用,什么也不返回”的概念,以及“复制构造”和“销毁”的辅助概念,并将其包装到一个整洁的小包装中。

所以你可以做

void groot () { std::cout << "I am groot!\n"; }
std::function<void()> f = groot;
f();

并调用 groot。或者,我们可以将lambda或函数对象, std::bind表达式或 boost::function传递给 std::function并调用它。

所有这些类型都可以被复制,销毁和调用: std::function可以使用它们并生成一个运行时接口(interface)。除了它们支持的操作之外, std::function可以存储和执行的类型无关。没有将函数 groot与lambda或 boost::function关联的类层次结构。
std::function<void()>的构造函数采用非 std::function的类型,在复制,销毁和带有签名 void()的概念下对其参数进行类型擦除。

我们从这个开始:
template<class Sig>
struct func_type_eraser;

template<class R, class... Args>
struct func_type_eraser<R(Args...)> {
// invoke:
virtual R operator()(Args...) const = 0;
// copy:
virtual func_type_eraser* clone() const = 0;
// destroy:
virtual ~func_type_eraser() {};
};
template<class Sig, class T>
struct func_type_eraser_impl; // TODO!

在这里,我们有复制,销毁和调用的3个概念,每个概念都表示为一个纯虚函数。
template<class Sig>
struct function;
template<class R, class... Args>
struct function<R(Args...)> {
std::unique_ptr<func_type_eraser<R(Args...)>> pImpl;
// invoke:
R operator()( Args... args ) const {
return (*pImpl)( std::forward<Args>(args)... );
}
// destroy:
~function() = default;
// copy:
function(function const& o) : pImpl( o.pImpl ? o.pImpl->clone() : nullptr ) {}
// move:
function(function&&) = default;
// TODO: operator=

// technical issues, ignore:
function(function& o) : function(const_cast<function const&>(o)) {}
function(function const&& o) : function(o) {}

// type erase:
template<class T>
function(T&& t) : pImpl( new func_type_eraser_impl<R(Args...), std::decay_t<T>>{std::forward<T>(t)} )
{}
};

在这里,我们将要支持的概念包装成所谓的 Regular类型-值类型类型。我们有一个底层的指针和虚拟层次结构(一个很小的层次,尚未见到),但是 function类型看起来就像一个 int一样-您可以对其进行复制,分配等。

每个概念(调用,复制,移动,销毁)都转发到 pImpl( move除外,我们可以在此层有效地实现该概念)。

此处仅完成类型擦除工作的一半。这部分使我们可以为 function类实例分配任何内容。我们可以通过测试 T通过概念要求来做得更好-可以将它复制,销毁并使用所需的签名进行调用-在将其提交给我们的构造函数之前。 (当前的C++ std::function无法做到这一点,非常烦人)。

类型擦除的最后一部分是:
template<class R, class... Args, class T>
struct func_type_eraser_impl<R(Args...), T> : func_type_eraser<R(Args...)> {
// type erase storage:
T t;
// invoke:
virtual R operator()(Args... args) const override {
return t( std::forward<Args>(args)... );
}
// copy:
virtual func_type_eraser_impl* clone() const override {
return new func_type_eraser_impl{t};
}
// destroy:
virtual ~func_type_eraser_impl() {}
};

…我们在其中实现针对特定类型 func_type_eraserT中公开的概念接口(interface)。

现在我们有4个概念,其中3个是类型擦除的,一个由常规类型包装器处理,我们可以存储支持这3个概念的任何东西。

我们可以更进一步:

我们甚至可以支持客户可以提供支持这些概念的功能的任何东西。

最简单的方法是在允许ADL(依赖于参数的查找)的上下文中调用诸如 std::begin之类的自由函数。

使用我们的类型擦除实现,而不是直接与对象交互,而是在ADL上下文中调用free函数。

提供该函数的默认实现,该实现执行从“失败”到“检查方法 .begin()并调用它”或“执行低效版本”或“检查传递的类型的属性,并确定执行此操作的合理方式”的任何操作任务”。

通过这种技术,我们可以允许客户扩展我们的类型擦除,并使用更广泛的概念。

举一个具体的例子,假设我们有可打印的概念。如果 ostream << X重载,或者 print(X)重载,则可以打印。

我们将 print_it添加到我们的类型擦除接口(interface)。它是 using impl_namespace::print,然后执行 print(t)
impl_namespace::print(X)只是执行一个 cout << X

这一切都是解耦的。您可以采用其他人编写的没有打印概念的类型,通过其命名空间中的自由函数添加打印概念,然后将其传递给我们的类型擦除系统,然后类型擦除系统将其连接起来。

有关使用某人使用相似技术构建具有无限撤消和显示功能的玩具文档的示例,请参见 this channel 9 video的示例,该文档可以扩展为任意数量的类型,包括内置类型。

现在,想象一下对此的语言支持。能够描述您要键入擦除的一组概念,并说出“构建擦除这些类型的常规类型”。

如果您有所述其他概念支持的算法,则可以说“对该算法的类型擦除支持”。任何知道算法类型擦除并且对其有更好支持的客户端都可以自动将自定义创建的客户端添加到您的界面中。那些不能使用您提供的类型擦除概念来实现它的人。

在类型擦除时,即从编译时对概念的理解到虚拟以及运行时,即使您类型上对概念的支持是概念图,对算法的类型擦除支持也可能非常有效。基于(即提供解决问题的自定义函数。您的类型不是天真的可复制的,但是有一个克隆函数可将其复制到合适的存储中)。算法概念类型擦除可以考虑完整的编译时概念映射,而不是运行时虚拟概念映射,即使没有根本上较快的算法也可以提高性能。

如果格外小心,则可以使用带有较少概念的类型擦除对象,如果新概念受较少概念的支持,则可以将其扩展为包含更多概念的类型。那些“不知道”您想要快速二进制搜索(例如)的客户最终会从其运行时界面中支持它:那些确实会为您提供针对您的类型定制的快速二进制搜索的客户。

采取进一步的措施,您可以在类型擦除类中获得可选的概念支持。例如,类型擦除迭代器可能会选择支持随机访问迭代。接受迭代器的算法可能会测试随机访问迭代,如果这样,则会创建一个更好的实现。在范围上进行二进制搜索的概念可能会检查该范围是否具有二进制搜索概念支持,如果没有,则是否具有随机访问支持,并且使用二进制搜索的前向迭代器版本失败(O(n)前进,O(lg( n))比较)。在每种情况下,它都可以使用“更专业”的实现。

所有这些都与概念在编译时的工作方式相似。除此以外,它在运行时发生,并具有额外的类型擦除系统。

关于c++ - 什么是C++运行时概念?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26185268/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com