关于this question,有人能解释一下并发布元编程的示例代码吗?我在谷歌上搜索了这个术语,但我找不到任何例子来说服我,它可以有任何实际用途。
同样,Qt's Meta Object System是元编程的一种形式吗?
jrh
发布于 2009-06-11 12:00:30
到目前为止,大多数示例都对值进行了操作(计算pi的位数,N的阶乘或类似的值),这些都是教科书上的示例,但它们通常不是很有用。很难想象有哪种情况下你真的需要编译器来计算pi的第17位。你可以自己硬编码,也可以在运行时计算。
一个可能与现实世界更相关的例子可能是:
假设我们有一个数组类,其大小是一个模板参数(因此这将声明一个由10个整数组成的数组:array<int, 10>)
现在我们可能想要连接两个数组,并且我们可以使用一些元编程来计算得到的数组大小。
template <typename T, int lhs_size, int rhs_size>
array<T, lhs_size + rhs_size> concat(const array<T, lhs_size>& lhs, const array<T, rhs_size>& rhs){
array<T, lhs_size + rhs_size> result;
// copy values from lhs and rhs to result
return result;
}这是一个非常简单的例子,但至少这些类型与现实世界有某种相关性。此函数在编译时生成大小正确的数组,并且具有完全的类型安全性。它正在计算一些我们不能通过硬编码值(我们可能想要连接许多具有不同大小的数组)或在运行时(因为那样我们就会丢失类型信息)所能轻松完成的工作。
不过,更常见的情况是,您倾向于使用元编程来处理类型,而不是值。
在标准库中可以找到一个很好的例子。每种容器类型都定义了自己的迭代器类型,但普通的老式指针也可以用作迭代器。从技术上讲,需要一个迭代器来公开许多类型定义成员,比如value_type,而指针显然不能做到这一点。因此,我们使用一些元编程来说明“哦,但是如果迭代器类型被证明是一个指针,那么它的value_type应该使用这个定义。”
关于这一点,有两点需要注意。第一个是我们操作的是类型,而不是值我们不是说“N的阶乘是某某”,而是“类型T的value_type被定义为...”
第二件事是它被用来促进泛型编程。(如果迭代器不适用于所有最简单的示例,即指向数组的指针,那么迭代器就不是一个非常通用的概念。因此,我们使用一些元编程来填充指针被视为有效迭代器所需的细节)。
这是元编程的一个相当常见的用例。当然,您可以将其用于广泛的其他用途(表达式模板是另一个常用的示例,旨在优化开销很大的计算,Boost.Spirit是一个完全超负荷的示例,允许您在编译时定义自己的解析器),但最常见的用途可能是消除这些需要特殊处理并使泛型编程不可能实现的小问题和小问题。
发布于 2009-06-11 11:17:45
这个概念完全来自于Meta-这个名字,意思是从它的前缀中抽象出来。
用更多的“对话风格”来做一些事情,而不是事情本身。
在这一点上,元编程本质上是编写代码,这会编写(或导致编写)更多代码。
C++模板系统是元编程,因为它不是简单地进行文本替换(就像c预处理器所做的那样),而是具有(复杂且低效的)与代码结构交互的方法,它解析输出的代码要复杂得多。在这方面,C++中的模板预处理是图灵完成的。这并不是说某些东西是元编程的要求,但几乎可以肯定的是,这足以被算作元编程。
可参数化的代码生成工具可以被认为是元编程,如果它们的模板逻辑足够复杂。
系统越接近于使用表示语言的抽象语法树(与我们表示语言的文本形式相反),就越有可能被认为是元编程。
从QT MetaObjects代码来看,我不会(粗略地检查一下)将其称为元编程,因为它通常是为C++模板系统或Lisp宏之类的东西而保留的。它看起来仅仅是一种在编译阶段向现有类注入某些功能的代码生成形式(它可以看作是当前流行的面向方面编程风格的先驱,也可以看作是JavaScripts等语言中基于原型的对象系统的先驱
作为你可以在C++中使用的极端长度的例子,有一个Boost MPL,它的tutorial向你展示了如何获得:
Dimensioned types (测量单位)
quantity<float,length> l( 1.0f );
quantity<float,mass> m( 2.0f );
m = l; // compile-time type errorHigher Order Metafunctions
twice(f,x) := f(f(x))
template <class F, class X>
struct twice
: apply1<F, typename apply1<F,X>::type>
{};
struct add_pointer_f
{
template <class T>
struct apply : boost::add_pointer<T> {};
};现在,我们可以在add_pointer_f中使用两次来构建指向指针的指针:
BOOST_STATIC_ASSERT((
boost::is_same<
twice<add_pointer_f, int>::type
, int**
>::value
));发布于 2009-06-11 11:32:11
虽然它很大(2000loc),但我在c++中创建了一个自反式类系统,它独立于编译器,包括对象编组和元数据,但没有存储开销或访问时间损失。它是核心元编程,用于一个非常大的在线游戏中,用于映射游戏对象以进行网络传输和数据库映射(ORM)。
无论如何,它需要一段时间来编译,大约需要5分钟,但它的好处是它的速度与每个对象的手动调优代码一样快。因此,它通过减少服务器上的大量CPU时间(CPU使用率是以前的5% )节省了大量资金。
https://stackoverflow.com/questions/980492
复制相似问题