我正在尝试理解什么是元编程,以及它在C++中的具体含义。如果我搜索c++元编程,我确实得到了模板元编程(TMP)的教程,但没有解释它是只对模板的特定用法进行分类,还是对模板的所有用法进行分类。
我的问题是,C++中模板的所有使用是否都被归类为元编程。解释为什么它是或不是也是有帮助的。谢谢。
发布于 2020-01-05 18:16:42
我的问题是,C++中模板的所有使用是否都被归类为元编程。
不是的。
在C++中,并非模板的所有用法都是元编程。
显然,这是一个定义问题,但在C++中,“元编程”是“编译时计算”的同义词。
因此,对于模板,我们做元编程(特别是模板元编程),但并不是所有模板的使用都是元编程。
一个简单的反例
template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
{ std::cout << k << ": " << v << std::endl; }前面的printKeyVal()是一个模板函数,它将两个泛型值输出到标准输出(所以是运行时,而不是编译时)。
它不能运行编译时,所以它是“模板”,而不是“元编程”。
更一般地说:std::vector是一个使用内存分配的模板类。并且不能在编译时代码中使用内存分配(直到C++17;也许将来可能会有所不同)。
因此,std::vector (与具有固定大小的不使用内存分配的std::array相反)是一个不能用于元编程的模板特性(当使用涉及std::vector对象的实例化时)。
发布于 2020-01-05 19:57:26
什么是C++中的TMP?
C++中的模板元编程是一种使用C++模板在编译时表示和执行任意算法的技术。它通常通过使用模板专门化来模拟条件分支,并使用递归模板定义来模拟循环。最著名的例子是编译时阶乘计算:
template <unsigned int n>
struct factorial {
// recursive definition to emulate a loop or a regular recursion
enum { value = n * factorial<n - 1>::value };
};
// specialization that describes "break" condition for the recursion
template <>
struct factorial<0> {
enum { value = 1 };
};它使用了上述两种技术。
然而,更常见的是使用TMP进行类型检测和转换,而不是实际的数值计算,例如标准的std::is_pointer实用程序(source):
// generic definition that emulates "false" conditional branch
template<class T>
struct is_pointer_helper : std::false_type {};
// a specialization that emulates "true" conditional branch
template<class T>
struct is_pointer_helper<T*> : std::true_type {};
template<class T>
struct is_pointer : is_pointer_helper< typename std::remove_cv<T>::type > {};标准type_traits报头提供的大多数实用程序都是使用TMP技术实现的。
鉴于TMP算法是使用类型定义来表示的,值得一提的是,TMP是一种declarative programming形式,其中计算逻辑是在不使用显式控制流语句(if、else、for等)的情况下表达的。
C++模板的所有用法都是元编程吗?
简短的答案是:不。如果模板不是用来表达编译时算法的,那么它就不是元编程,而是。
在C++中引入模板的主要目标是实现泛型编程,即允许重用相同的算法(find、copy、sort等)。和数据结构(vector、list、map等)用于满足特定要求的任何类型,包括用户定义的类型。
事实上,C++中的TMP是discovered by accident,并不是模板的预期用途。
总之: C++中的模板元编程是使用模板来表达编译时算法,大多数(全部?)C++模板的其他用途是泛型编程的一种形式。
发布于 2020-01-06 01:47:43
我正在尝试理解什么是元编程,以及它在C++中的具体含义
你还没有说出你对元编程的理解,所以你的答案没有一个共同的起点。
我假设wikipedia definition已经足够好了:
元编程是一种编程技术,其中计算机程序具有将其他程序视为其数据的能力。
..。可用于将计算从运行时移动到编译时,使用编译时计算生成代码...
C++通常不允许自修改代码,所以我忽略了这一点。我还选择不计算预处理器,因为在编译时(或者可以说是在编译之前)进行文本替换与对程序的语义进行操作是不同的。
我的问题是,C++中模板的所有用法是否都归类为元编程
不,它不是。
考虑一下,作为参考:
#define MAX(a,b) ((a) > (b) ? (a) : (b))这是不使用模板就可以编写泛型(类型无关) max函数的松散方式。我已经说过,我不把预处理器算作元编程,但在任何情况下,每当使用它时,它都会生成相同的代码。
在以后的translation phase中,它只是委托解析代码,并担心类型和是否将a>b定义给编译器。这里没有任何东西在编译时运行来产生不同的结果代码,这取决于...什么都行。在编译时,不计算任何内容。
现在,我们可以比较模板版本:
template <typename T>
T max(T a, T b) { return a > b ? a : b; }这并不是简单地执行文本替换。实例化的过程更加复杂,可以考虑名称查找规则和重载,并且在某种意义上不同的实例化可能不是文本等价的(例如,一个可以使用bool ::operator< (T,T)和一个bool T::operator<(T const&)或其他任何东西)。
但是,每个实例化的含义是相同的(假设不同类型的operator<定义兼容,等等)。除了编译器通常的解析类型和名称等(机械的)过程之外,在编译时不会进行任何计算。
顺便说一句,你的程序只包含让编译器告诉它该做什么的指令肯定是不够的,因为这是所有编程都要做的。
现在,有一些边缘情况,比如
template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };它们确实将计算转移到了编译时(在本例中是非终止的,因为我不想费心编写最终案例),但可以说它们不是元编程。
尽管维基百科的定义提到了将计算转移到编译时,但这只是一个值计算-它并没有对代码的结构或语义做出编译时的决定。
https://stackoverflow.com/questions/59598338
复制相似问题