什么时候/为什么(如果有的话)我应该考虑做通用编程/元编程 [英] When/Why ( if ever ) should i think about doing Generic Programming/Meta Programming

查看:105
本文介绍了什么时候/为什么(如果有的话)我应该考虑做通用编程/元编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



但是,当涉及到泛型程序设计/元程序



- 这是一个新的编程/设计范式吗?



- 它只是局限于图书馆发展吗?如果没有,那么什么设计/编码情况需要使用元编程/通用编程。



- 使用模板意味着我在做泛型编程?



我已经在这个话题上了很多,但是不要完全掌握大图。
另请参阅帖子。 p>




在这里阅读下面的讨论,直到现在,正确):



a)通用编程和元程序是两个不同的概念。

解决方案

元编程是一个非常异乎寻常的话题。有趣的是,它是一个强大的工具,有时你会发现它有用。但它永远不会是你工具箱中最常用的工具。有时,您可能希望您的代码对具有不同属性的一系列不相关类型进行操作,这就是元编程的地方。有了一些诡计,您可以写一个函数的重载,只有当参数类型是整数,或者如果它是一个指针,或者它是类型X,Y或Z(可能忽略Z上的constness)。



它本质上是用类型编程。通常,你的程序可以做两个数字,并产生第三个数字,或告诉你一个数字是否满足一些要求。元编程可以采用两种类型,并产生第三种类型,或告诉您类型是否满足一些要求。是的,它可能是最有用的图书馆发展。但是再次,大多数代码可以被视为库代码。你可以说,main()函数之外的一切都是库代码。



通常,如果你想通过元编程解决一个问题,你可能想使用相关的boost库做得很繁重。 Boost.TypeTraits当然Boost.Mpl可以真正简化你的事情。



通用编程是相关的(而且,可能在某些情况下使用元编程在真正的通用,例如标准库使用触摸元编程将原始指针转换为有效的迭代器,这是迭代器概念是通用的),但不完全相同。



每次你实例化一个 std :: vector 。每次使用一对迭代器来处理一系列值时,都会使用通用编程。通用编程只是一个想法,你的代码应该尽可能通用,并应该工作,无论什么类型放入它。 std :: vector不需要包含类型来实现ICanBeContained接口(记住Java需要从Object派生所有东西,以便将它存储在容器类中,这意味着原始类型被装箱,



使用迭代器对序列进行迭代的代码是通用的,可以使用任何类型的迭代器,或者甚至使用简单指针。



通用编程非常有用,通常可以在很大程度上替代OOP。 (见上面的例子,为什么我写一个容器,需要包含的类型来实现一个接口,如果我可以避免这个限制?)



通常,当你使用接口在OOP,它不是允许类型在运行时改变(虽然当然也发生不时),但允许你在编译时交换另一种类型(也许在测试期间注入一个模拟对象,而不是使用完整的实现),或者只是解耦两个类。通用编程可以做到这一点,而不需要做繁琐的定义和维护接口的工作。在这些情况下,通用编程意味着您必须编写和维护较少的代码,并且获得更好的性能和更好的类型安全性。所以是的,你应该肯定感觉在家里与泛型编程。 C ++不是一个非常好的OOP语言。如果你想严格遵守OOP,你应该切换到Java或其他更多的OOP固定语言。 C ++ 允许写入OO代码,但它通常不是最好的解决方案。有一个原因,为什么几乎整个标准库依赖于泛型编程,而不是OOP。标准库中有很少的继承或多态性。他们不需要它,代码变得更简单的使用和更强大没有它。



并回答你的其他问题,是的,通用编程几乎是一个单独范式。模板元编程不是。这是一个相当具体的操作类型系统的技术,非常好解决少数问题。被认为是一个范例,我认为它必须是更通用的,和方法你可以使用基本上一切,如功能,OO或通用编程。



我认为xtofl真的很好:通用编程是让你的代码类型不知道。 (A std :: vector does not care ,或需要知道中存储的是什么类型。)



另一方面,元编程是关于类型计算的。给定类型T0和T1,我们可以定义类型T2,就像我们可以,给定整数N0和N1,我们可以定义一个N2,它是N0和N1的和。



Boost.Mpl库有一个很明显的例子。
在普通代码中,如果你有整数N0,N1和N2,你可以创建一个包含这三个值的std :: vector。我可以使用一些其他算法来计算索引,然后提取存储在向量中该位置的值。



给定类型T0,T1和T2,我们可以创建包含这三种类型的mpl :: vector。
现在我可以使用一些其他算法在编译时计算索引,并提取存储在向量中该位置的类型


IMHO to me OOPS, design patterns make sense and i have been able to apply them practically.

But when it comes to "generic programming /meta programming" of the Modern C++ kind, i am left confused.

-- Is it a new programming/design paradigm ?

-- Is it just limited to "library development"? If not, What design/coding situations call for using meta programming/generic programming.

-- Does using templates mean i am doing generic programming?

I have googled a lot on this topic but do not grasp the BIG PICTURE fully. Also see this post.


After reading dicussions here under, up till now, I am sure ( might still not be correct):

a) Generic programming and meta programming are two different concepts.

解决方案

Metaprogramming is a pretty exotic topic. It's interesting to learn about, it's a powerful tool, and occasionally you might find it useful. But it'll never be the most often used tool in your toolbox. Sometimes, you might want your code to act on a range of unrelated types with different properties, and that's where metaprogramming comes in. With a bit of trickery, you can write an overload of a function that is only available if the argument type is integral, or if it is a pointer, or if it is either type X, Y, or Z (perhaps ignoring constness on Z).

It is essentially programming with types. Normally, your program can do things like take two numbers and produce a third number, or tell you whether a number satisfies some requirement. Metaprogramming can take two types and produce a third type, or tell you whether a type satisfies some requirement. And yes, it is probably mostly useful in library development. But then again, most code could be considered library code. You could say that everything outside your main() function is library code.

Usually, if you want to solve a problem through metaprogramming, you'll probably want to use the relevant boost libraries to do the heavy lifting. Boost.TypeTraits and of course Boost.Mpl can really simplify things for you. But it's not something you need to know, and it's not something you're likely to need very often.

Generic programming is related (and may in some cases use metaprogramming under the hood to become really generic, for example the standard library uses a touch of metaprogramming to turn raw pointers into valid iterators which is required for the "iterator" concept to be generic), but not entirely the same. And it is much more widely used.

Every time you instantiate a std::vector, you use generic programming. Every time you use a pair of iterators to process a sequence of values, you use generic programming. Generic programming is just the idea that your code should be as generic as possible, and should work regardless of what types are put into it. A std::vector doesn't require the contained type to implement a "ICanBeContained" interface (remember how Java requires everything to be derived from Object in order for it to be stored in a container class? Which means primitive types get boxed, and that we lose type safety. That's not generic, and it's a pointless restriction.)

The code to iterate over a sequence using iterators is generic, and works with any type of iterators, or even with plain pointers.

Generic programming is very widely useful, and can often to a large extent replace OOP. (see the above example. Why would I write a container that required the contained types to implement an interface, if I can avoid that limitation?)

Often, when you use interfaces in OOP, it is not to allow the type to change during runtime (although of course that happens from time to time too), but to allow you to swap in another type at compile-time (perhaps injecting a mock object during tests, rather than using the full-fledged implementation), or just to decouple two classes. Generic programming can do that, without having you do the tedious work of defining and maintaining the interface. In those cases, generic programming means you have to write and maintain less code, and you get better performance and better type-safety. So yes, you should definitely feel at home with generic programming. C++ isn't a very good OOP language. If you want to stick strictly with OOP, you should switch to Java or another more more OOP-fixated language. C++ allows you to write OO code, but it's often not the best solution. There's a reason why almost the entire standard library relies on generic programming, rather than OOP. There is very little inheritance or polymorphism in the standard library. They didn't need it, and the code became simpler to use and more powerful without it.

And to answer your other questions, yes, Generic programming is pretty much a separate paradigm. Template metaprogramming is not. It is a fairly specific technique for manipulating the type system, and is very good at solving a small number of problems. To be considered a paradigm, I think it'd have to be much more generally useful, and approach you can use for basically everything, like functional, OO or generic programming.

I think xtofl really nailed it: Generic programming is about making your code type-unaware. (A std::vector doesn't care, or need to know what type is stored in it. It just works.)

Metaprogramming on the other hand, is about type computations. Given type T0 and T1, we can define a type T2, just like how we can, given integers N0 and N1, we can define a N2 that is the sum of N0 and N1.

The Boost.Mpl library has an obvious example of this. In your normal code, if you have the integers N0, N1 and N2, you can create a std::vector containing these three values. I can then use some other algorithm to compute an index, and then extract the value stored at that location in the vector.

Given types T0, T1 and T2, we can create a mpl::vector containing these three types. I can now use some other algorithm to compute an index at compile-time, and extract the type stored at that location in the vector.

这篇关于什么时候/为什么(如果有的话)我应该考虑做通用编程/元编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆