Is there any examples out there where template metaprogramming would be better to use than the new constexpr? From what I've understood, both constexpr and template metaprogramming have similar purposes, yet template metaprogramming is not obsolete. So there has to be some examples where template metaprogramming is preferred over constexpr. Any shared thoughts on this would be highly appreciated, thanks!

- 3,059
- 3
- 28
- 50

- 689
- 1
- 9
- 16
-
2How do you propose to achieve, say, compile-time polymorphism with `constexpr`? – lapk Mar 28 '15 at 21:49
-
1Related: http://stackoverflow.com/q/6016771/560648 – Lightness Races in Orbit Mar 28 '15 at 21:51
-
I think your wording of *looking for examples* makes people feel this is off-topic while what you are really trying to do is understand when tmp is required and constexpr is not an option. – Shafik Yaghmour Mar 28 '15 at 21:55
2 Answers
constexpr
provides true support for compile-time computing in the form of true C++ functions instead of functional-like template-based constructions (Metafunctions). So partially the answer is yes constexpr beats tmp on compile time computing, at least on its syntax for no fp initiated people used to C++. Note that I'm ignoring concerns about compiler performance etc.
On the other hand, tmp is still relevant, and actually the only way, to do type computing in C++. There are new approaches to improve the horrible tmp syntax, like what Boost.Hana does with template variables. But despite the syntax, is still a functional metalanguage separated from "normal" C++.
About type computing
From the two common tasks you may ask a C++ compiler for (Besides compiling), playing with the type system generating new types on demand depending on your requisites is something that constexpr cannot achieve, simply because that's not what constexpr is supposed/designed to do.
The fun part is that templates were not supposed to do compile-time computing neither. Even metaprogramming. They were designed as the C++ feature for generic programming. But you know the story, middle 90s "Whoaaa C++ templates are turing complete!", expression templates and blitz++ later, then Alexandrescu and his Loki. And now we have <type_traits>
and a serious proposal with a full fledged metaprogramming library inside.
Consider this example (Not mine, taken from this Eric Niebler "challenge"): Write an utility that gives you the common type between a set of types:
namespace m = ranges::meta;
namespace ml = ranges::meta::lazy;
template<typename T, typename U>
using builtin_common_t =
decltype(true? std::declval<T>() : std::declval<U>());
template<typename T, typename U>
using lazy_builtin_common_t =
m::defer<builtin_common_t, T, U>;
template<typename...Ts>
struct common_type
{};
template<typename ...Ts>
using common_type_t = m::eval<common_type<Ts...>>;
template<typename T>
struct common_type<T>
: std::decay<T>
{};
template<typename T, typename U>
struct common_type<T, U>
: m::if_c<
( std::is_same<decay_t<T>, T>::value &&
std::is_same<decay_t<U>, U>::value ),
ml::let<lazy_builtin_common_t<T, U>>,
common_type<decay_t<T>, decay_t<U>>>
{};
template<typename T, typename U, typename... Vs>
struct common_type<T, U, Vs...>
: ml::let<ml::fold<m::list<U, Vs...>, T, m::quote<common_type_t>>>
{};
As you can see, this problem is about types. Something that constexpr is not supposed to do.
About the challenge, Eric asked both Louis Dionne (Boost.Hana author) and I to write common_type<Ts...>
using our libraries. Code above is Eric's implementation using his Meta library. Sincerely, I cannot beat Louis's fold + maybe monad solution :)

- 13,969
- 4
- 40
- 75
-
Your first paragraph is basically the argument Sumant Tambe [makes in the example for using constexpr instead in my answer here](http://stackoverflow.com/a/21519186/1708801) .. I am curious do you have an example that can fit in a typical SO answer of when tmp is required? – Shafik Yaghmour Mar 28 '15 at 21:52
-
@ShafikYaghmour as far I'm concerned constexpr is more expensive from the compiler point of view that common template recursive instantiations. Actually the default max recursion limit of constexpr is much more less than the tmp one. On the other hand, C++14 constexpr allows loops. So no rec is required almost never. – Manu343726 Mar 28 '15 at 21:58
-
@ShafikYaghmour so maybe the answer is: Use constexpr for compile-time computing. The point is that almost nobody does pure compile-time computing, but play with types instead. And constexpr has nothing to do there. – Manu343726 Mar 28 '15 at 21:59
-
1Could you elaborate on type computing in terms of this question? What it means in the discussion of whether to prefer template metaprogramming over constexpr? This is a really great answer though, thanks! – Forever a noob Mar 28 '15 at 22:14
-
Literally any time you want to create a suite of related types that differ only in some of the types used therein. How would you implement std::vector<T>
with only constexpr
?
Templates and constexpr
perform different jobs, though in some cases an old template implementation may be swapped for a more concise version with constexpr
. These cases are hardly exhaustive, though.

- 1
- 1

- 378,754
- 76
- 643
- 1,055
-
5I think OP talks about _template metaprogramming_ and `constexpr`, not about templates' use in general. – lapk Mar 28 '15 at 21:55
-
@Petr: The use of templates is template metaprogramming. – Lightness Races in Orbit Mar 28 '15 at 21:57
-
Correct me if I'm wrong, but I thought _template metaprogramming_ is about "performing computations" during compile time. In my understanding it's only a subset of template usage. I mean, `std:vector
` is a template, but not an example of a _template metaprogramming_. – lapk Mar 28 '15 at 22:03 -
For almost every C++ programmer templates are `std::vector
` and have nothing to do with metaprogramming. – Manu343726 Mar 28 '15 at 22:03 -
@Petr: "Template metaprogramming (TMP) is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled. The output of these templates include compile-time constants, data structures, and complete functions." When you define a template `std::vector`, you are metaprogramming. You're not programming your C++ code: you're _metaprogramming_. The result is a type `std::vector
` or a type `std::vector – Lightness Races in Orbit Mar 28 '15 at 22:04` etc that you then do regular programming with. -
Executing value computations with templates is just one branch of template metaprogramming, and it's the only branch that can be solved instead with `constexpr`. Therefore, _every other usage_ cannot be solved with `constexpr`, which is the answer. – Lightness Races in Orbit Mar 28 '15 at 22:05
-
@Manu343726: Not really relevant how many C++ programmers get it wrong! – Lightness Races in Orbit Mar 28 '15 at 22:06
-
3Even if the template mechanism generates code under the hood and that's a type of metaprogramming, you know perfectly what the community knows as tmp: There are simple templates as glorified Java generics (That are the C++ templates for 90% of C++ programmers), and there are complex ones where you compute types, generate new classes, do complex specializations, traits, etc (TMP, templates for C++ mads). – Manu343726 Mar 28 '15 at 22:08
-
@Manu343726: I am honestly lost as to what you're talking about. TMP is what I quoted the definition of above. If you have some C++ programmer friends who get the definition wrong then that is their problem! Your answer is great though and I'd already upvoted it. So this is pretty pointless. – Lightness Races in Orbit Mar 28 '15 at 22:09
-
2What I mean is that the OP asked about TMP, **asked about the common definition of TMP**. Maybe you are right, not the correct TMP def, but still what people understands as TMP. Keep in mind that people will read the topic in the future and talking about TMP == templates may mislead them. Is that incorrect and we should talk about tmp properly? That's a completely different topic. *An interesting topic which deserves a question here I think* – Manu343726 Mar 28 '15 at 22:13
-
1Maybe I'm wrong, but I understand `std::vector
` code not as _metaprogramming_, but as _generic progamming_. When I go and use `std::vector – lapk Mar 28 '15 at 22:21` there is a _metaprogramming_ part of instantiation - compiler does instantiation processing generic code. In this respect I agree with you - every time one uses template there is a metaprogramming part. Anyway, I think it was a good discussion. Thanks, guys. -
There are no generics in C++. Perhaps you're thinking of Java! – Lightness Races in Orbit Mar 28 '15 at 23:30
-
-
@LightnessRacesinOrbit It seems you have very unconventional definitions. C++ templates are exactly the tool for generic programing. STL in C++ is an example of generic programming, and was designed and implemented by Stepanov who is all about generic programming (wrote a library in Ada first, then moved to C++ and made STL; tried to convince Stroustrup to introduce generics in C++ initially)... – lapk Mar 29 '15 at 01:47
-
1