Is all use of templates in C++ metaprogramming?
Asked Answered
W

4

15

I'm trying to understand what metaprogramming is general and what it is in C++ in particular. If I search for c++ metaprogramming I do get tutorials of template metaprogramming (TMP), but no explanation of if it only categorizes a specific use of templates or all usages of templates.

My question is if all usages of templates in C++ is categorized as metaprogramming. An explanation of why it is or isn't would also be helpful. Thank you.

Whin answered 5/1, 2020 at 8:55 Comment(3)
Compare to CL macros and see Greenspun's tenth rule. en.wikipedia.org/wiki/Greenspun%27s_tenth_ruleUnsuitable
TMP is not the only way for metaprogramming. One can also do metaprogramming with macros (uhh) and constexpr functions. Constexpr can be easier to implement than TMP.Houseclean
@Houseclean I'm unsure whether merely executing code at compile time is what should be considered "metaprogramming". Because that's not programming, but computing. It's merely shifting execution from runtime to compile time. Metaprogramming in C++ is different than that, because it generates code (templates, macros).Enchanter
L
6

My question is if all usages of templates in C++ is categorized as metaprogramming.

No.

Not all usages of templates, in C++, are metaprogramming.

Obviously it's a question of definitions but, in C++, "metaprogramming" is synonymous of "compile-time computation".

So with templates we do metaprogramming (specifically template metaprogramming) but not all uses of templates are metaprogramming.

A simple counter-example

template <typename K, typename V>
void printKeyVal (K const & k, V const & v)
 { std::cout << k << ": " << v << std::endl; }

The preceding printKeyVal() is a template function that print, to standard output (so run-time, not compile-time), a couple of generic values.

It can't run compile-time so it's "template" but isn't "metaprogramming".

More in general: std::vector is a template class that uses memory allocation. And memory allocation (till C++17; maybe in future can be different) can't be used in compile-time code.

So std::vector (contrary to std::array that, having a fixed size, doesn't use memory allocation) is a template feature that can't be used (when the use involve the instantiation of a std::vector object) for metaprogramming.

Linoel answered 5/1, 2020 at 10:16 Comment(5)
Still, any function that depends on template, requires at least some metaprogramming. In your example the printKeyVal is defined during compile time according to the templated argumentsPhotolysis
When you program, you write code. You don't "compute" things. So I would define "metaprogramming" as "writing code to write code". And this is exactly what every template is about. I'm aware that template metaprogramming is often used for the "compile time computation"-y thing, but I would personally use a different term for that (I'm sure I haven't done so in the past, so apologies).Enchanter
@JohannesSchaub-litb - It's matter of language and definitions (and I have the additional handicap that I don't know well the English language) and I'm agree that a definition of "metaprogramming" that include all templates is possible and maybe also reasonable. What I say is that, in C++ community, the term "metaprogramming" is used with a different meaning that intersect but doesn't include all template uses. Maybe I'm wrong... could be an interesting poll.Linoel
Maybe it's called "metaprogramming" only if the code of the template is not anmore 1:1 duplicated for each type, because if it's 1:1 duplicated then the template code is purly passive and all "meta-programming" is done by the compiler. If there's some specialization or static-if or overload-dispatching or something, it's the code itself that decides what will be generated. This appears to be D's stance: tour.dlang.org/tour/en/gems/template-meta-programmingEnchanter
@Photolysis - It seems to me that you're using a definition of "metaprogramming" that, perfectly legit and maybe also reasonable, is different from the one that the C++ community is, de facto, using: rougly speaking: "metaprogramming == compile time execution". Maybe I'm wrong and the community uses mainly a definition that include all template uses... could be an interesting poll, I suppose.Linoel
K
4

What is TMP in C++?

Template metaprogramming (TMP) in C++ is a technique for expressing and executing arbitrary algorithms in compile-time using C++ templates. It is usually enabled by the use of template specialization to emulate conditional branches and recursive template definition to emulate loops. The most well-known example is a compile-time factorial computation:

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 };
};

which uses both of the aforementioned techniques.

A far more common, however, is a use of TMP for type detection and transformation rather than actual numeric computation, e.g. a standard std::is_pointer utility (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 > {};

Most of the utilities provided by the standard type_traits header are implemented using TMP techniques.

Given that TMP algorithms are expressed using type definitions, it's worth mentioning that TMP is a form of declarative programming in which the logic of computation is expressed without the use of explicit control flow statements (if, else, for, etc...).

Is all usage of C++ templates a metaprogramming?

The short answer is: No. If the templates aren't used for expressing a compile-time algorithm then it's not a metaprogramming, it's a generic programming.

The primary goal for introducing templates in C++ was to enable generic programming, that is to allow reusing the same algorithms (find, copy, sort, etc...) and data structures (vector, list, map, etc...) for any types, including user-defined ones, that satisfy certain requirements.

In fact TMP in C++ was discovered by accident and was not the intended use of templates.


In summary: Template metaprogramming in C++ is the use of templates to express a compile-time algorithm, most (all?) other uses of C++ templates is a form of generic programming.

Karlow answered 5/1, 2020 at 11:57 Comment(0)
B
1

I'm trying to understand what metaprogramming is general and what it is in C++ in particular

You haven't said what you understand by metaprogramming in general yet, so your answers don't have a common starting point.

I'm going to assume the wikipedia definition is good enough for this:

Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data.

... can be used to move computations from run-time to compile-time, to generate code using compile time computations ...

C++ doesn't generally allow self-modifying code, so I'm ignoring that. I'm also choosing not to count the preprocessor, as textual substitution at (or arguably just before) compile time is not the same as operating on the semantics of the program.

My question is if all usages of templates in C++ is categorized as metaprogramming

No, it is not.

Consider, for reference:

#define MAX(a,b) ((a) > (b) ? (a) : (b))

which is loosely the way to write a generic (type-agnostic) max function without using templates. I've already said I don't count the preprocessor as metaprogramming, but in any case it always produces identical code whenever it is used.

It simply delegates parsing that code, and worrying about types and whether a>b is defined to the compiler, in a later translation phase. Nothing here operates at compile time to produce different resulting code depending on ... anything. Nothing, at compile time, is computed.

Now, we can compare the template version:

template <typename T>
T max(T a, T b) { return a > b ? a : b; }

This does not simply perform a textual substitution. The process of instantiation is more complex, name lookup rules and overloads may be considered, and in some sense different instantiations may not be textually equivalent (eg. one may use bool ::operator< (T,T) and one bool T::operator<(T const&) or whatever).

However, the meaning of each instantiation is the same (assuming compatible definitions of operator< for different types, etc.) and nothing was computed at compile time apart from the compiler's usual (mechanical) process of resolving types and names and so on.

As an aside, it's definitely not enough that your program contains instructions for the compiler to tell it what to do, because that's what all programming is.

Now, there are marginal cases like

template <unsigned N>
struct factorial() { enum { value = N * factorial<N-1>::value }; };

which do move a computation to compile time (and in this case a non-terminating one since I can't be bothered to write the terminal case), but are arguably not metaprogramming.

Even though the Wikipedia definition mentioned moving computations to compile time, this is only a value computation - it's not making a compile-time decision about the structure or semantics of your code.

Brickwork answered 5/1, 2020 at 17:47 Comment(0)
C
-1

When writing C++ functions with templates, you are writing "instructions" for the compiler to tell it what to do when encountering calls of the function. In this sense, you are not directly writing code, therefore we call it meta-programming.

So yes, every C++ code involving templates is considered meta-programming

Note that only the parts defining templates functions or classes are meta-programming. Regular functions and classes are categorized as regular C++ !

Caravan answered 5/1, 2020 at 9:0 Comment(11)
Not all uses of programming languages should be considered programming either.Moving
@n.'pronouns'm. The OP specifically asked about C++, I don't understand your remarkCaravan
When I type "cp a.txt b.txt" in Bash this is not programming even though I am using a full blown programming environment. Likewise when I use std::vector I instruct a compiler to produce a program (so it's meta indeed) but the instruction itself is hardly a program. Most people don't consider using macros "metaprogramming".Moving
@n.'pronouns'm. I think I see what you mean: i am writing about the declarations/definitions while you are writing about the usage. Then, it is true that template function declaration s meta-programming and that usage is not (eg. std::vector<int> )Caravan
You answer is simply wrong! Please read the other answers given in this thread to get a basic understanding what MTP means!Fecundity
Plus 1, for me this is closer to what is considered "meta programming", according to wikipedia.Enchanter
Whenever you write C++ without templates, you are writing instructions for the compiler. So the fact that templates tell the compiler what to do, cannot be sufficient to distinguish programming from metaprogrammingBrickwork
Sorry... not sure to understand your last note... your definition of "metaprogramming" imply that only template function and classes are metaprogramming? I mean... a non-template constexpr function (a trivial example: constexpr int sum (int a, int b) { return a+b; }) is metaprogramming or not, for you?Linoel
@Brickwork but the fact that templates tell the compiler to generate other templates or final "leaf" code can be sufficient.Enchanter
@JohannesSchaub-litb In the context of C++, the term "metaprogrammation" has a specific meaning which differs from its general meaning. IIRC it initially referred to the discovered C++ feature coined by A.Alexandrescu in its book Modern C++ Design. The classical use of template in C++ isn't metaprogrammation (unless you use the non-C++ term metaprogrammation).Statesman
From OP's question: "I'm trying to understand what metaprogramming is general and what it is in C++ in particular". So I guess your angle is fine and would constitute an excellent answer. But this one isn't. -1Statesman

© 2022 - 2024 — McMap. All rights reserved.