C++11 Metaprogramming

Hi All, I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated. TIA, -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 04/01/2012 04:12 AM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
From a pure meta-programming perspective, I guess the only real addition is variadic templates. However, there is the problem that they're fairly limited and that one may not expand them as the arguments of a non-variadic template. Since I need to integrate with other libraries and tools, I therefore use them very rarely. One very useful use of variadic templates however is with function templates. They allow to make a function template with 0 arguments, which wasn't possible in C++03. This can be used to delay instantiation of the function body which can be necessary if name resolution needs to happen later. This is also possible with the new function template default arguments. A new possibility with C++11 is the use of SFINAE to test arbitrary expressions. I have not found this to be particularly useful in practice, however. Detecting nested types is often good enough. decltype is very useful. I use it in some meta-programming contexts to select a type when I need best-match selection: type0 f(input_iterator_tag); type1 f(forward_iterator_tag); type2 f(bidirectional_iterator_tag); typedef decltype(f(typename std::iterator_traits<T>::iterator_category())) result; The only thing we could do before C++11 was return a type with a unique size, then associate that size to a type.

On 01.04.2012, at 15:24, Mathias Gaunard wrote:
One very useful use of variadic templates however is with function templates. They allow to make a function template with 0 arguments, which wasn't possible in C++03. This can be used to delay instantiation of the function body which can be necessary if name resolution needs to happen later.
But if the argument pack expands to nothing, doesn't that mean that there isn't anything dependent to delay lookup in the first place? Sebastian

On 04/01/2012 06:15 PM, Sebastian Redl wrote:
On 01.04.2012, at 15:24, Mathias Gaunard wrote:
One very useful use of variadic templates however is with function templates. They allow to make a function template with 0 arguments, which wasn't possible in C++03. This can be used to delay instantiation of the function body which can be necessary if name resolution needs to happen later.
But if the argument pack expands to nothing, doesn't that mean that there isn't anything dependent to delay lookup in the first place?
It doesn't know the argument pack expands to nothing until it's instantiated.

From a pure meta-programming perspective, I guess the only real addition is variadic templates. However, there is the problem that they're fairly limited and that one may not expand them as the arguments of a non-variadic template.
I thought that was allowed. At least, GCC supports it since 4.7, and its error message for it in 4.6 was "sorry, unimplemented: cannot expand 'Args ...' into a fixed-length argument list" which suggests the feature is not an extension. Regards, Nate

From a pure meta-programming perspective, I guess the only real addition is variadic templates. However, there is the problem that they're fairly limited and that one may not expand them as the arguments of a non-variadic template.
I thought that was allowed. At least, GCC supports it since 4.7, and its error message for it in 4.6 was
"sorry, unimplemented: cannot expand 'Args ...' into a fixed-length argument list"
which suggests the feature is not an extension.
The relevant GCC bug report is PR 35722 [1]. It is mentioned there that the change that made this valid was the incorporation of N2555 [2]. Note in particular the sentence in section 14.3 paragraph 8 that was struck. Regards, Nate [1] http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35722 [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf

On 1 Apr 2012, at 22:07, Nathan Ridge wrote:
From a pure meta-programming perspective, I guess the only real addition is variadic templates. However, there is the problem that they're fairly limited and that one may not expand them as the arguments of a non-variadic template.
I thought that was allowed. At least, GCC supports it since 4.7, and its error message for it in 4.6 was
"sorry, unimplemented: cannot expand 'Args ...' into a fixed-length argument list"
which suggests the feature is not an extension.
There is a workaround for this, redirect through another layer of templates template<template <typename...> T, typename... Args> struct Join { typedef T<Args...> type; }; Chris

First, to all who replied, let me say "thank you!" Now, on to the fun part... on Sun Apr 01 2012, Mathias Gaunard <mathias.gaunard-AT-ens-lyon.org> wrote:
On 04/01/2012 04:12 AM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
From a pure meta-programming perspective, I guess the only real addition is variadic templates.
Well, I disagree, but... I'm not going to bother listing all the other things I think are relevant here because they'll be discussed elsewhere in the thread...
However, there is the problem that they're fairly limited and that one may not expand them as the arguments of a non-variadic template. Since I need to integrate with other libraries and tools, I therefore use them very rarely.
I don't understand what you mean by "them" in "expand them." Argument packs can certainly be expanded in arguments to non-variadic templates. For example, template <class...Ts> struct vector {}; template <class Sequence> struct non_variadic {}; template <class...Ts> struct foo : non_variadic<vector<Ts...> > {}; But I'm sure you knew that already. The inability to handle argument packs directly without wrapping them in something like vector is a real limitation, though.
One very useful use of variadic templates however is with function templates. They allow to make a function template with 0 arguments, which wasn't possible in C++03. This can be used to delay instantiation of the function body which can be necessary if name resolution needs to happen later.
...which almost seems like cheating ;-)
This is also possible with the new function template default arguments.
Ah, yes.
A new possibility with C++11 is the use of SFINAE to test arbitrary expressions. I have not found this to be particularly useful in practice, however.
Agreed. It's often hard to draw any definite conclusions about user intentions based on valid expressions, because of false positives.
Detecting nested types is often good enough.
decltype is very useful. I use it in some meta-programming contexts to select a type when I need best-match selection: type0 f(input_iterator_tag); type1 f(forward_iterator_tag); type2 f(bidirectional_iterator_tag); typedef decltype(f(typename std::iterator_traits<T>::iterator_category())) result;
The only thing we could do before C++11 was return a type with a unique size, then associate that size to a type.
Yep. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 04/03/2012 01:14 PM, Dave Abrahams wrote:
I don't understand what you mean by "them" in "expand them."
I meant template parameter packs.
Argument packs can certainly be expanded in arguments to non-variadic templates. For example,
template<class...Ts> struct vector {}; template<class Sequence> struct non_variadic {}; template<class...Ts> struct foo : non_variadic<vector<Ts...> > {};
But I'm sure you knew that already. The inability to handle argument packs directly without wrapping them in something like vector is a real limitation, though.
I meant the inability to do template<class T0 = void, class T1 = void, class T2 = void> struct mpl_vector {}; template<class... T> struct c11_vector : mpl_vector<T...> {}; But apparently, this is now allowed.

Hi, On 2012-04-01 02:12:24 +0000, Dave Abrahams said:
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11 (...) I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
Below are a few tricks I've used with varying success with the trunk version of clang and libc++ with C++11 compilation turned on. Some might be obvious, some not, but at least they are some improvement over their C++03 counterparts. The text turned out to be quite lengthy, so here's a link to a syntax-colored and more reader-friendly Gist: https://gist.github.com/2275320 See you all in Aspen! /Pyry Jahkola * * * 1) Using variadic class templates recursively, like in the definitions for "add<T...>" here: #include <type_traits> // A few convenience aliases first template <typename T, T N> using ic = std::integral_constant<T, N>; template <int N> using int_ = std::integral_constant<int, N>; // Sum any number of integral constants: template <typename... Args> struct add; template <> struct add<> : ic<int, 0> {}; template <typename A> struct add<A> : ic<decltype(+A::value), A::value> {}; template <typename A, typename B, typename... More> struct add<A, B, More...> : add<ic<decltype(A::value + B::value), A::value + B::value>, More...> {}; // --- example -------------------------------------------------------- add<>::value; // 0 add<int_<1>>::value; // 1 add<int_<1>, int_<2>>::value; // 3 add<int_<1>, int_<2>, int_<3>>::value; // 6 add<int_<1>, int_<2>, int_<3>, int_<4>>::value; // 10 // etc. * * * 2a) With decltype, the "sizeof(yes_type)" trick is no longer needed for implementing traits. This one tests whether there is a type T::type defined: using std::true_type; using std::false_type; namespace detail { template <typename T, typename Type=typename T::type> struct has_type_helper; template <typename T> true_type has_type_test(has_type_helper<T> *); template <typename T> false_type has_type_test(...); } template <typename T> struct has_type : decltype(detail::has_type_test<T>(nullptr)) {}; // --- example -------------------------------------------------------- has_type<int>::value; // false has_type<std::is_integral<int>>::value; // true, said type is "bool" has_type<std::integral_constant<int,1>>::value; // true, said type is "int" 2b) This trait tests whether T is an integral constant: namespace detail { template <typename T, decltype(T::value)> struct integral_constant_helper; template <typename T> true_type integral_constant_test( integral_constant_helper<T,T::value> *); template <typename T> false_type integral_constant_test(...); } template <typename T> struct is_integral_constant : decltype(detail::integral_constant_test<T>(nullptr)) {}; // --- example -------------------------------------------------------- is_integral_constant<int>::value; // false is_integral_constant<std::is_integral<int>>::value; // true (IC true) is_integral_constant<std::integral_constant<int,1>>::value; // true (IC one) * * * 3) Selection of the first matching type from a list of cases (or pattern matching, if you will): template <typename... When> struct match; template <> struct match<> { static constexpr bool value = false; }; template <typename When, typename... More> struct match<When, More...> : std::conditional<When::value, When, match<More...>>::type {}; // 'match' is meant to be used together with 'when', 'otherwise' and friends: template <bool Cond, typename Then=void> struct when_c; template <typename Then> struct when_c<true, Then> { typedef Then type; static constexpr bool value = true; }; template <typename Then> struct when_c<false, Then> { static constexpr bool value = false; }; template <bool Cond, typename Then=void> struct when_not_c : when_c<!Cond, Then> {}; template <typename Cond, typename Then=void> struct when : when_c<Cond::value, Then> {}; template <typename Cond, typename Then=void> struct when_not : when_not_c<Cond::value, Then> {}; template <typename Then> struct otherwise { typedef Then type; static constexpr bool value = true; }; // --- example -------------------------------------------------------- struct fizz {}; struct buzz {}; struct fizzbuzz {}; template <int N> struct game : match< when_c<N % 3 == 0 && N & 5 == 0, fizzbuzz>, when_c<N % 3 == 0, fizz>, when_c<N % 5 == 0, buzz>, otherwise< int_c<N>> > {}; game<1>::type; // int_<1> game<2>::type; // int_<2> game<3>::type; // fizz game<4>::type; // int_<4> game<5>::type; // buzz game<6>::type; // fizz game<7>::type; // int_<7> game<8>::type; // int_<8> game<9>::type; // fizz game<10>::type; // buzz game<11>::type; // int_<11> game<12>::type; // fizz game<13>::type; // int_<13> game<14>::type; // int_<14> game<15>::type; // fizzbuzz game<16>::type; // int_<16> * * * 4a) Variadic template template parameters. For instance, boost::mpl::quoteN<...> can be reimplemented with just: template <template <typename...> class F> struct quote { template <typename... Args> struct apply : F<Args...> {}; }; 4b) Here's another use for variadic template template parameters. Of course, the standard library offers std::tuple_size<T> for getting the number of elements in a tuple. But that metafunction cannot be used for any other tuple-like class. Suppose we defined boost::mpl::vector like: template <typename... T> struct vector {}; By using a variadic template template, we can define a metafunction which works equally for both std::tuple<T...> as well as vector<T...>: template <typename T> struct size {}; // (no size defined by default) template <template <typename...> class C, typename... T> struct size<C<T...>> : ic<std::size_t, sizeof...(T)> {}; template <typename T> struct size<T &> : size<T> {}; template <typename T> struct size<T &&> : size<T> {}; template <typename T> struct size<T const> : size<T> {}; template <typename T> struct size<T volatile> : size<T> {}; template <typename T> struct size<T const volatile> : size<T> {}; // --- example -------------------------------------------------------- size<tuple<int, int> &>::value; // 2 size<vector<int, int, int>>::value; // 3 size<vector<> const &>::value; // 0 * * * 5) Using nested variadic templates to get many template parameter packs to play with: namespace detail { template <typename A> struct con; template <typename... T> struct con<vector<T...>> { template <typename B> struct cat; template <typename... U> struct cat<vector<U...>> { typedef vector<T..., U...> type; }; }; } template <typename A, typename B> struct concat : detail::con<A>::template cat<B> {}; // --- example -------------------------------------------------------- struct a; struct b; struct c; struct d; struct e; concat<vector<a, b>, vector<c, d, e>>::type; // vector<a, b, c, d, e> * * * 6) Defining function result and result type at once. #define RETURNS(...) decltype((__VA_ARGS__)) { return (__VA_ARGS__); } // --- example -------------------------------------------------------- template <typename A, typename B> auto plus(A const & a, B const & b) -> RETURNS(a + b) It can't be used with recursive definitions like here, though: struct mul_ { int operator()() const { return 1; } template <typename A> A operator()(A const & a) const { return a; } // template <typename A, typename B, typename... C> // auto operator()(A const & a, B const & b, C const &... c) const -> // RETURNS(mul_()(a * b, c...)) // --> Error: invalid use of incomplete type mul_ // std::declval helps, but duplicates the multiplication part: template <typename A, typename B, typename... C> auto operator()(A const & a, B const & b, C const &... c) const -> decltype(std::declval<mul_>()(a * b, c...)) { return mul_()(a * b, c...); } }; constexpr mul_ mul = {}; // global function object // --- example -------------------------------------------------------- mul(); // 1 mul(10); // 10 mul(10, -20, 30.0); // -6000.0 * * * 7) Counted template recursion. The function "apply_tuple(f, t)" calls the function (function object) "f" with the elements of the tuple "t" as arguments. (To simplify things a bit, I omitted the perfect forwarding support in this example.) The count is tracked with a total number of iterations N, and the running index I. R is the precalculated result type. namespace detail { template <typename R, std::size_t N, std::size_t I=0> struct apply_tuple { template <typename F, typename T, typename... Args> R operator()(F f, T const & t, Args const &... args) const { typedef apply_tuple<R, N, I + 1> next; return next()(f, t, args..., std::get<I>(t)); } }; template <typename R, std::size_t N> struct apply_tuple<R, N, N> { template <typename F, typename T, typename... Args> R operator()(F f, T const &, Args const &... args) const { return f(args...); } }; } template <typename F, typename... T> decltype(std::declval<F>()(std::declval<T const &>()...)) apply_tuple(F f, std::tuple<T...> const & t) { typedef decltype(std::declval<F>()(std::declval<T const &>()...)) result; return detail::apply_tuple<result, sizeof...(T)>()(f, t); } // --- example -------------------------------------------------------- int f(int a, int b) { return a + b; } apply_tuple(f, std::make_tuple(10, 20)); // 30 auto t = std::make_tuple(10, -20, 30.0); apply_tuple(mul, t); // -6000.0 * * * -- Pyry Jahkola · http://pyrtsa.posterous.com pyry.jahkola@iki.fi · http://twitter.com/pyrtsa Attending C++Now! 2012

on Sun Apr 01 2012, Pyry Jahkola <pyry.jahkola-AT-iki.fi> wrote:
Hi,
On 2012-04-01 02:12:24 +0000, Dave Abrahams said:
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11 (...) I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
Below are a few tricks I've used with varying success with the trunk version of clang and libc++ with C++11 compilation turned on. Some might be obvious, some not, but at least they are some improvement over their C++03 counterparts.
The text turned out to be quite lengthy, so here's a link to a syntax-colored and more reader-friendly Gist: https://gist.github.com/2275320
See you all in Aspen! /Pyry Jahkola
Looking forward to it!
3) Selection of the first matching type from a list of cases (or pattern matching, if you will):
template <typename... When> struct match; template <> struct match<> { static constexpr bool value = false; }; template <typename When, typename... More> struct match<When, More...> : std::conditional<When::value, When, match<More...>>::type {};
// 'match' is meant to be used together with 'when', 'otherwise' and friends:
template <bool Cond, typename Then=void> struct when_c; template <typename Then> struct when_c<true, Then> { typedef Then type; static constexpr bool value = true; }; template <typename Then> struct when_c<false, Then> { static constexpr bool value = false; };
template <bool Cond, typename Then=void> struct when_not_c : when_c<!Cond, Then> {};
template <typename Cond, typename Then=void> struct when : when_c<Cond::value, Then> {};
template <typename Cond, typename Then=void> struct when_not : when_not_c<Cond::value, Then> {};
template <typename Then> struct otherwise { typedef Then type; static constexpr bool value = true; };
Do the uses of constexpr here add anything w.r.t. plain const?
4a) Variadic template template parameters. For instance, boost::mpl::quoteN<...> can be reimplemented with just:
template <template <typename...> class F> struct quote { template <typename... Args> struct apply : F<Args...> {}; };
4b) Here's another use for variadic template template parameters. Of course, the standard library offers std::tuple_size<T> for getting the number of elements in a tuple. But that metafunction cannot be used for any other tuple-like class. Suppose we defined boost::mpl::vector like:
template <typename... T> struct vector {};
By using a variadic template template, we can define a metafunction which works equally for both std::tuple<T...> as well as vector<T...>:
template <typename T> struct size {}; // (no size defined by default)
template <template <typename...> class C, typename... T> struct size<C<T...>> : ic<std::size_t, sizeof...(T)> {};
template <typename T> struct size<T &> : size<T> {}; template <typename T> struct size<T &&> : size<T> {}; template <typename T> struct size<T const> : size<T> {}; template <typename T> struct size<T volatile> : size<T> {}; template <typename T> struct size<T const volatile> : size<T> {};
// --- example --------------------------------------------------------
size<tuple<int, int> &>::value; // 2 size<vector<int, int, int>>::value; // 3 size<vector<> const &>::value; // 0
Cute.
5) Using nested variadic templates to get many template parameter packs to play with:
namespace detail { template <typename A> struct con; template <typename... T> struct con<vector<T...>> { template <typename B> struct cat; template <typename... U> struct cat<vector<U...>> { typedef vector<T..., U...> type; }; }; }
template <typename A, typename B> struct concat : detail::con<A>::template cat<B> {};
// --- example --------------------------------------------------------
struct a; struct b; struct c; struct d; struct e;
concat<vector<a, b>, vector<c, d, e>>::type; // vector<a, b, c, d, e>
Interesting formulation. I used: template <class ...Ss> struct append_; template <class ...T1s> struct append_<vector<T1s...> > : vector<T1s...> {}; template <class ...T1s, class ...T2s> struct append_<vector<T1s...>, vector<T2s...> > : vector<T1s...,T2s...> {}; template <class ...T1s, class ...Ss> struct append_<vector<T1s...>, Ss...> : append_<vector<T1s...>, typename append_<Ss...>::type> {}; Does the nested class template arrangement have any advantages?
* * *
6) Defining function result and result type at once.
#define RETURNS(...) decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
// --- example --------------------------------------------------------
template <typename A, typename B> auto plus(A const & a, B const & b) -> RETURNS(a + b)
Totally. I have used // RETURNS() is used to avoid writing boilerplate "->decltype(x) { return x; }" phrases. // // USAGE: auto function(<arguments>) RETURNS(<some-expression>); // // Note: we end with a unique typedef so the function can be followed // by a semicolon. If we omit the semicolon, editors get confused and // think we haven't completed the function declaration. #define RETURNS(...) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } typedef int RETURNS_CAT(RETURNS_, __LINE__) // Standard PP concatenation formula #define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y) Probably it's a good idea to incorporate noexcept: #define RETURNS(...) noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) -> decltype(__VA_ARGS__) { return (__VA_ARGS__); } typedef int RETURNS_CAT(RETURNS_, __LINE__)
It can't be used with recursive definitions like here, though:
struct mul_ { int operator()() const { return 1; }
template <typename A> A operator()(A const & a) const { return a; }
// template <typename A, typename B, typename... C> // auto operator()(A const & a, B const & b, C const &... c) const -> // RETURNS(mul_()(a * b, c...))
// --> Error: invalid use of incomplete type mul_ } };
Heh, try (*this) instead of mul_(). That works until you try to incorporate noexcept as suggested above (at least on GCC 4.7). After that you have to do something like this: --8<---------------cut here---------------start------------->8--- struct mul_ { int operator()() const { return 1; } template <typename A> A operator()(A const & a) const noexcept(noexcept(A(std::move(a)))) { return a; } // ****** workaround ****** static mul_ get() noexcept { return mul_(); } template <typename A, typename B, typename... C> auto operator()(A const & a, B const & b, C const &... c) const RETURNS(get()(a * b, c...)); }; --8<---------------cut here---------------end--------------->8--- very annoying.
7) Counted template recursion. The function "apply_tuple(f, t)" calls the function (function object) "f" with the elements of the tuple "t" as arguments. (To simplify things a bit, I omitted the perfect forwarding support in this example.)
The count is tracked with a total number of iterations N, and the running index I. R is the precalculated result type.
namespace detail { template <typename R, std::size_t N, std::size_t I=0> struct apply_tuple { template <typename F, typename T, typename... Args> R operator()(F f, T const & t, Args const &... args) const { typedef apply_tuple<R, N, I + 1> next; return next()(f, t, args..., std::get<I>(t)); } };
template <typename R, std::size_t N> struct apply_tuple<R, N, N> { template <typename F, typename T, typename... Args> R operator()(F f, T const &, Args const &... args) const { return f(args...); } }; }
template <typename F, typename... T> decltype(std::declval<F>()(std::declval<T const &>()...)) apply_tuple(F f, std::tuple<T...> const & t) { typedef decltype(std::declval<F>()(std::declval<T const &>()...)) result; return detail::apply_tuple<result, sizeof...(T)>()(f, t); }
// --- example --------------------------------------------------------
int f(int a, int b) { return a + b; } apply_tuple(f, std::make_tuple(10, 20)); // 30
auto t = std::make_tuple(10, -20, 30.0); apply_tuple(mul, t); // -6000.0
Isn't it a bit slicker to do this by creating an argument pack of integers and expanding that with get<Is>(t)... ? --8<---------------cut here---------------start------------->8--- template <class T, T I, class S> struct cons_c; template <template <class T, T...> class S, class T, T I, T ...Is> struct cons_c<T, I, S<T, Is...> > : S<T,I,Is...> {}; template <class T, T ...Is> struct vector_c { typedef vector_c type; }; template <std::size_t N> struct count_ : cons_c<std::size_t, N-1, typename count_<N-1>::type> {}; template <> struct count_<0> : vector_c<std::size_t> {}; template <std::size_t N> using count = typename count_<N>::type; #include <tuple> template <typename F, typename Tuple , std::size_t ...Is> auto apply_tuple(F f, Tuple const & t, vector_c<std::size_t, Is...>) RETURNS(f(std::get<Is>(t)...)); template <typename F, typename ...T> auto apply_tuple(F f, std::tuple<T...> const & t) RETURNS(apply_tuple(f, t, count<sizeof...(T)>())); --8<---------------cut here---------------end--------------->8--- -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 2012-04-03 15:57:34 +0000, Dave Abrahams said:
template <typename Then> struct otherwise { typedef Then type; static constexpr bool value = true; };
Do the uses of constexpr here add anything w.r.t. plain const?
Not to my knowledge (or correct me if it does!). I just acquired this habit from the way the C++11 standard library defined constants like the following in the FDIS: namespace std { template <class T, T v> struct integral_constant { static constexpr T value = v; typedef T value_type; typedef integral_constant<T,v> type; constexpr operator value_type() { return value; } }; }
5) Using nested variadic templates to get many template parameter packs to play with:
(...)
template <typename A, typename B> struct concat : detail::con<A>::template cat<B> {};
Interesting formulation. I used:
(...)
template <class ...T1s, class ...T2s> struct append_<vector<T1s...>, vector<T2s...> > : vector<T1s...,T2s...> {};
Ha! Obviously I had missed the possibility that you can have several parameter packs in a template specialization as long as the pack expansions don't appear subsequently in the signature.
Does the nested class template arrangement have any advantages?
I tried to think of some, but couldn't yet come up with any. I find your alternative even better.
6) Defining function result and result type at once.
Totally. I have used
// RETURNS() is used to avoid writing boilerplate "->decltype(x) { return x; }" phrases. // // USAGE: auto function(<arguments>) RETURNS(<some-expression>);
I like the trick of requiring a semicolon here.
Probably it's a good idea to incorporate noexcept: (...)
True. I decided to postpone the use of noexcept until I get other things to work, so I'm still missing all the little tricks there are with noexcept. (Keen to hear about them in May!)
It can't be used with recursive definitions like here, though:
// template <typename A, typename B, typename... C> // auto operator()(A const & a, B const & b, C const &... c) const -> // RETURNS(mul_()(a * b, c...))
// --> Error: invalid use of incomplete type mul_
Heh, try (*this) instead of mul_(). That works until you try to incorporate noexcept as suggested above (at least on GCC 4.7).
Yep, same thing on clang: as soon as I enable noexcept in the RETURNS(...) macro, it gives "error: invalid use of 'this' outside of a nonstatic member function".
// ****** workaround ****** static mul_ get() noexcept { return mul_(); }
I'm not sure which one is correct here, GCC or Clang, but but this trick had a similar result: "error: calling 'get' with incomplete return type 'mul_'". The only alternative way I could fix it was to define a function returning a reference, e.g.: struct mul_ { // ... static mul_ const & get() noexcept; }; constexpr mul_ mul = {}; inline mul_ const & mul_::get() noexcept { return mul; }
very annoying.
Indeed.
7) Counted template recursion.
Isn't it a bit slicker to do this by creating an argument pack of integers and expanding that with get<Is>(t)... ?
Oh, sure! I wonder how I missed that. Yes, converting a template argument pack into an equal-length index sequence is very useful.
--8<---------------cut here---------------start------------->8--- template <class T, T I, class S> struct cons_c;
template <template <class T, T...> class S, class T, T I, T ...Is> struct cons_c<T, I, S<T, Is...> > : S<T,I,Is...> {};
template <class T, T ...Is> struct vector_c { typedef vector_c type; };
template <std::size_t N> struct count_ : cons_c<std::size_t, N-1, typename count_<N-1>::type> {};
template <> struct count_<0> : vector_c<std::size_t> {};
template <std::size_t N> using count = typename count_<N>::type;
#include <tuple>
template <typename F, typename Tuple , std::size_t ...Is> auto apply_tuple(F f, Tuple const & t, vector_c<std::size_t, Is...>) RETURNS(f(std::get<Is>(t)...));
template <typename F, typename ...T> auto apply_tuple(F f, std::tuple<T...> const & t) RETURNS(apply_tuple(f, t, count<sizeof...(T)>())); --8<---------------cut here---------------end--------------->8---
So thanks, I'm happy to hide this trick into my sleeve! ;) -- Pyry Jahkola · http://pyrtsa.posterous.com pyry.jahkola@iki.fi · http://twitter.com/pyrtsa Attending C++Now! 2012

on Tue Apr 03 2012, Pyry Jahkola <pyry.jahkola-AT-iki.fi> wrote:
Not to my knowledge (or correct me if it does!). I just acquired this habit from the way the C++11 standard library defined constants like the following in the FDIS:
namespace std { template <class T, T v> struct integral_constant { static constexpr T value = v; typedef T value_type; typedef integral_constant<T,v> type; constexpr operator value_type() { return value; } }; }
Hm. I don't know. I wonder what the purpose of those four characters is?
6) Defining function result and result type at once.
Totally. I have used
// RETURNS() is used to avoid writing boilerplate "->decltype(x) { return x; }" phrases. // // USAGE: auto function(<arguments>) RETURNS(<some-expression>);
I like the trick of requiring a semicolon here.
It makes editors behave, anyway.
Probably it's a good idea to incorporate noexcept: (...)
True. I decided to postpone the use of noexcept until I get other things to work, so I'm still missing all the little tricks there are with noexcept. (Keen to hear about them in May!)
Well, it certainly can't hurt to add the clause when everything's deduced anyway.
It can't be used with recursive definitions like here, though:
// template <typename A, typename B, typename... C> // auto operator()(A const & a, B const & b, C const &... c) const -> // RETURNS(mul_()(a * b, c...))
// --> Error: invalid use of incomplete type mul_
Heh, try (*this) instead of mul_(). That works until you try to incorporate noexcept as suggested above (at least on GCC 4.7).
Yep, same thing on clang: as soon as I enable noexcept in the RETURNS(...) macro, it gives "error: invalid use of 'this' outside of a nonstatic member function".
// ****** workaround ****** static mul_ get() noexcept { return mul_(); }
I'm not sure which one is correct here, GCC or Clang, but but this trick had a similar result: "error: calling 'get' with incomplete return type 'mul_'".
The only alternative way I could fix it was to define a function returning a reference, e.g.:
struct mul_ { // ...
static mul_ const & get() noexcept; };
constexpr mul_ mul = {};
inline mul_ const & mul_::get() noexcept { return mul; }
very annoying.
Indeed.
I think it's a GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52869
7) Counted template recursion.
Isn't it a bit slicker to do this by creating an argument pack of integers and expanding that with get<Is>(t)... ?
Oh, sure! I wonder how I missed that. Yes, converting a template argument pack into an equal-length index sequence is very useful.
Don't feel bad; I "missed it" too, until learned about it from someone else ;-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 04/03/2012 10:26 PM, Pyry Jahkola wrote:
Yep, same thing on clang: as soon as I enable noexcept in the RETURNS(...) macro, it gives "error: invalid use of 'this' outside of a nonstatic member function".
// ****** workaround ****** static mul_ get() noexcept { return mul_(); }
I'm not sure which one is correct here, GCC or Clang, but but this trick had a similar result: "error: calling 'get' with incomplete return type 'mul_'".
The only alternative way I could fix it was to define a function returning a reference
Could it be that the compiler forces instantiation of the code inside noexcept, like earlier MSVC versions did with decltype? Not sure what the standard says about this.

On Mar 31, 2012, at 10:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
The fact that noexcept(expression) is a compile-time bool is like unwrapping a shiny new toy on your birthday. :-) Howard

on Sun Apr 01 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
On Mar 31, 2012, at 10:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
The fact that noexcept(expression) is a compile-time bool is like unwrapping a shiny new toy on your birthday. :-)
That's lovely, but... exactly how does noexcept play into the metaprogramming picture? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Apr 3, 2012, at 12:23 PM, Dave Abrahams wrote:
on Sun Apr 01 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
On Mar 31, 2012, at 10:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
The fact that noexcept(expression) is a compile-time bool is like unwrapping a shiny new toy on your birthday. :-)
That's lovely, but... exactly how does noexcept play into the metaprogramming picture?
For example, I used it to create an is_nothrow_swappable<A> trait (http://llvm.org/svn/llvm-project/libcxx/trunk/include/type_traits) so that I could write: struct B { A a; }; void swap(B& x, B& y) noexcept(__is_nothrow_swappable<A>::value) { swap(x.a, y.a); } instead of: using std::swap; void swap(B& x, B& y) noexcept( noexcept( swap(declval<A&>(), declval<A&>()))) { swap(x.a, y.a); } The latter gets very tedious when B has several members and/or bases. Howard

on Tue Apr 03 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
That's lovely, but... exactly how does noexcept play into the metaprogramming picture?
For example, I used it to create an is_nothrow_swappable<A> trait (http://llvm.org/svn/llvm-project/libcxx/trunk/include/type_traits) so that I could write:
struct B { A a; };
void swap(B& x, B& y) noexcept(__is_nothrow_swappable<A>::value) { swap(x.a, y.a); }
instead of:
using std::swap; void swap(B& x, B& y) noexcept( noexcept( swap(declval<A&>(), declval<A&>()))) { swap(x.a, y.a); }
The latter gets very tedious when B has several members and/or bases.
But isn't this a better way to relieve the tedium? #define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__) #define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y) ... auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...); -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Apr 3, 2012, at 1:44 PM, Dave Abrahams wrote:
on Tue Apr 03 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
That's lovely, but... exactly how does noexcept play into the metaprogramming picture?
For example, I used it to create an is_nothrow_swappable<A> trait (http://llvm.org/svn/llvm-project/libcxx/trunk/include/type_traits) so that I could write:
struct B { A a; };
void swap(B& x, B& y) noexcept(__is_nothrow_swappable<A>::value) { swap(x.a, y.a); }
instead of:
using std::swap; void swap(B& x, B& y) noexcept( noexcept( swap(declval<A&>(), declval<A&>()))) { swap(x.a, y.a); }
The latter gets very tedious when B has several members and/or bases.
But isn't this a better way to relieve the tedium?
#define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__)
#define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y)
...
auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...);
I hadn't seen that one before. I guess Bjarne isn't getting rid of the preprocessor yet... Howard

on Tue Apr 03 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
On Apr 3, 2012, at 1:44 PM, Dave Abrahams wrote:
on Tue Apr 03 2012, Howard Hinnant <howard.hinnant-AT-gmail.com> wrote:
But isn't this a better way to relieve the tedium?
#define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__)
#define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y)
...
auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...);
I hadn't seen that one before. I guess Bjarne isn't getting rid of the preprocessor yet...
Nope. I guess he's just made it all the more relevant ;-) -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 3 April 2012 10:44, Dave Abrahams <dave@boostpro.com> wrote:
But isn't this a better way to relieve the tedium?
#define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__)
#define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y)
...
auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...);
But is that really allowed? I could not get it to work on clang because the declaration of swap needs access to the members of the class and the class definition is incomplete at that point. Moving the definition of swap outside the class did not help because you need access to private members. Making swap friend also does not help because friend declaration also needs a matching noexcept specification. gcc 4.7 seems to be lenient regarding this check but clang is not. Alternatively, using std::tuple could help in reducing verbosity of noexcept specification Howard is alluding to. template<typename... T> struct is_nothrow_swappable_all { static std::tuple<T...> *t; enum { value = noexcept(t->swap(*t)) }; }; Assuming all members and bases are swapped using std::swap something like the following could be used. using namespace std; struct Base { ... }; // Assuming Base has a std::swap<Base> specialization class Test : struct Base { string str; complex<double> cd; map<int, string> m; public: void swap(Test &) noexcept(is_nothrow_swappable_all<Base, string, complex<double>, map<int, string>>::value) { ... } }; However, I don't think if we could use std::make_tuple to avoid spelling out types all over again due to the reasons mentioned above. I would love to stand corrected. Sumant

on Wed Apr 04 2012, Sumant Tambe <sutambe-AT-gmail.com> wrote:
On 3 April 2012 10:44, Dave Abrahams <dave@boostpro.com> wrote:
But isn't this a better way to relieve the tedium?
#define RETURNS(...) \ noexcept(noexcept(decltype(__VA_ARGS__)(std::move(__VA_ARGS__)))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__)
#define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y)
...
auto swap(B& x, B& y) RETURNS(swap(x.a,y.a), swap(x.b,y.b), ...);
But is that really allowed? I could not get it to work on clang because the declaration of swap needs access to the members of the class and the class definition is incomplete at that point.
Going back to Howard's original example: --8<---------------cut here---------------start------------->8--- struct B { A a; }; void swap(B& x, B& y) noexcept(__is_nothrow_swappable<A>::value) { swap(x.a, y.a); } --8<---------------cut here---------------end--------------->8--- B is certainly complete at the point swap is defined. I did have to make an adjustment to deal with the fact that swap returns void: --8<---------------cut here---------------start------------->8--- #include <utility> // Used to create a non-void object that we can pass to std::move // in case the expression is void. struct nonvoid { template <class T> friend auto operator,(T&& x, nonvoid) noexcept -> T&&; }; #define RETURNS(...) \ noexcept(noexcept( \ decltype(__VA_ARGS__)( \ std::move(((__VA_ARGS__),nonvoid())) \ ))) \ -> decltype(__VA_ARGS__) \ { return (__VA_ARGS__); } \ typedef int RETURNS_CAT(RETURNS_, __LINE__) #define RETURNS_CAT_0(x, y) x ## y #define RETURNS_CAT(x, y) RETURNS_CAT_0(x,y) struct A { friend void swap(A&,A&) noexcept {} }; struct B { A a; }; auto swap(B& x, B& y) RETURNS(swap(x.a,y.a)); int main() {} --8<---------------cut here---------------end--------------->8---
Moving the definition of swap outside the class did not help because you need access to private members. Making swap friend also does not help because friend declaration also needs a matching noexcept specification. gcc 4.7 seems to be lenient regarding this check but clang is not.
I see: with private members, this swap needs to be a friend and then you have the incomplete type problem: --8<---------------cut here---------------start------------->8--- class B { A a; friend auto swap(B& x, B& y) RETURNS(swap(x.a,y.a)); // Error; B is incomplete }; --8<---------------cut here---------------end--------------->8--- Well, you can get around it by templatizing :-) --8<---------------cut here---------------start------------->8--- struct A { friend void swap(A&,A&) noexcept {} }; namespace gcc_bug_workaround { // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52875 class B { A a; template <class T> friend auto swap(T& x, T& y) RETURNS(swap(x.a,y.a)); // Error; B is incomplete }; } using namespace gcc_bug_workaround; --8<---------------cut here---------------end--------------->8---
Alternatively, using std::tuple could help in reducing verbosity of noexcept specification Howard is alluding to.
<snip>
However, I don't think if we could use std::make_tuple to avoid spelling out types all over again due to the reasons mentioned above.
I would love to stand corrected.
I think the template trick serves to delay things till the class is defined, yes? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Hi Dave, That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value : https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp) This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well. Regards, Olivier. On Sun, Apr 1, 2012 at 3:12 AM, Dave Abrahams <dave@boostpro.com> wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
TIA,
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Yep, I see. However, I also have some questions about the utility of such traits. As I mentioned to Mathias, structural matching is always susceptible to false positives. What do you use this for? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 4/3/2012 10:20 AM, Dave Abrahams wrote:
on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Well, there's this: http://tinyurl.com/85sv5sy [*]
Yep, I see. However, I also have some questions about the utility of such traits. As I mentioned to Mathias, structural matching is always susceptible to false positives.
Unless I'm mistaken, you can't get my code to report a false positive. You can get it to fail to compile with an ambiguity error, but only if you go tinkering with extremely obscure language features. (E.g. by making an object callable by giving it an implicit conversion to a function pointer.) Anyway, the link describes a few cases in Proto where this trait is used, and others have found it useful. [*] There is a better implementation and a link to further discussion attached to the following feature request: https://svn.boost.org/trac/boost/ticket/3783 -- Eric Niebler BoostPro Computing http://www.boostpro.com

on Wed Apr 04 2012, Eric Niebler <eric-AT-boostpro.com> wrote:
On 4/3/2012 10:20 AM, Dave Abrahams wrote:
on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Well, there's this: http://tinyurl.com/85sv5sy [*]
Yes, but I think the OP was talking about detecting member function callability.
Yep, I see. However, I also have some questions about the utility of such traits. As I mentioned to Mathias, structural matching is always susceptible to false positives.
Unless I'm mistaken, you can't get my code to report a false positive.
I think you misunderstand what I mean by "false positive." I mean that structural queries (like "can you call this function with these parameters") are IME usually used as a concept check—which, when the goal is not to cause an error, is used for the purposes of dispatching to appropriate algorithm implementations. However, a type's /interface/ can always support a syntax that structurally resembles a concept without supporting the semantics, or even without being able to actually instantiate the operation struct looks_like_a_universal_function_object { template <class...Ts> void operator()(Ts&&...xs) { std::swap(xs...); } }; This is strictly a binary function object, but its interface doesn't say say.
You can get it to fail to compile with an ambiguity error, but only if you go tinkering with extremely obscure language features. (E.g. by making an object callable by giving it an implicit conversion to a function pointer.)
Anyway, the link describes a few cases in Proto where this trait is used, and others have found it useful.
OK, it looks like you're using the function object as a kind of "policies class," and the trait makes it more convenient than it otherwise might be to define such classes. Since you tell the user exactly how it will be interpreted and the user has full control over the class' definition, this works out fine. Yes, that's an important use-case for TMP. Thanks for clarifying. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

----- Original Message -----
From: Eric Niebler <eric@boostpro.com> To: boost@lists.boost.org Cc: Sent: Wednesday, April 4, 2012 1:59 AM Subject: Re: [boost] C++11 Metaprogramming
On 4/3/2012 10:20 AM, Dave Abrahams wrote:
on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small
piece of
code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Well, there's this: http://tinyurl.com/85sv5sy [*]
I wonder if this technique could be extended for member functions in C++03. Thanks, Paul Fultz II

On 03.04.2012, at 19:20, Dave Abrahams wrote:
on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Yep, I see. However, I also have some questions about the utility of such traits. As I mentioned to Mathias, structural matching is always susceptible to false positives. What do you use this for?
I have used something like this to define a generic Set concept (bool contains(const Set& set, const Value& value)). Since in this concept, every normal value represents its own singleton set, I have used is_callable to separate out functions and function-like objects that return bool. Sebastian

on Wed Apr 04 2012, Sebastian Redl <sebastian.redl-AT-getdesigned.at> wrote:
On 03.04.2012, at 19:20, Dave Abrahams wrote:
on Sun Apr 01 2012, Olivier Grant <olivier.grant-AT-gmail.com> wrote:
Hi Dave,
That's going to be an interesting presentation. Here is a small piece of code that allows to generate a traits structure that determines if a call can be made on an object with a specific function name and specific arguments and return value :
https://gist.github.com/2276393 (compile with : g++ -std=c++0x -Wall -o has_callable has_callable.cpp)
This was not possible in C++03, or at least not completely possible, and the code is much simpler with C++11 for the cases where it was possible as well.
Yep, I see. However, I also have some questions about the utility of such traits. As I mentioned to Mathias, structural matching is always susceptible to false positives. What do you use this for?
I have used something like this to define a generic Set concept (bool contains(const Set& set, const Value& value)). Since in this concept, every normal value represents its own singleton set, I have used is_callable to separate out functions and function-like objects that return bool.
Hm. Can you describe this concept more fully, e.g. with a requirements table or ConceptGCC syntax? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 05.04.2012, at 16:25, Dave Abrahams wrote:
on Wed Apr 04 2012, Sebastian Redl <sebastian.redl-AT-getdesigned.at> wrote:
I have used something like this to define a generic Set concept (bool contains(const Set& set, const Value& value)). Since in this concept, every normal value represents its own singleton set, I have used is_callable to separate out functions and function-like objects that return bool.
Hm. Can you describe this concept more fully, e.g. with a requirements table or ConceptGCC syntax?
concept Set<S, V> { bool contains(const S&, const V&); } template <typename V> concept_map Set<std::set<V>, V> { bool contains(const std::set<V>& s, const V& v) { return s.find(v) != s.end(); } } template <typename V> concept_map Set<bool, V> { bool contains(bool b, const V&) { return b; } } // various others, e.g. unordered_set. template <typename V, Callable<bool (V)> Fn> concept_map Set<Fn, V> { bool contains(Fn fn, const V& v) { return fn(v); } } template <EqualityComparable V> if no other concept_map matches concept_map Set<V, V> { bool contains(const V& s, const V& v) { return s == v; } } Specifically, I've used my is_callable to emulate the Callable concept in the enable_if of the contains() overload for functions, and the disable_if in the fallback version. Sebastian

on Fri Apr 06 2012, Sebastian Redl <sebastian.redl-AT-getdesigned.at> wrote:
Hm. Can you describe this concept more fully, e.g. with a requirements table or ConceptGCC syntax?
concept Set<S, V> { bool contains(const S&, const V&); }
template <typename V> concept_map Set<std::set<V>, V> { bool contains(const std::set<V>& s, const V& v) { return s.find(v) != s.end(); } }
template <typename V> concept_map Set<bool, V> { bool contains(bool b, const V&) { return b; } }
// various others, e.g. unordered_set.
template <typename V, Callable<bool (V)> Fn> concept_map Set<Fn, V> { bool contains(Fn fn, const V& v) { return fn(v); } }
template <EqualityComparable V> if no other concept_map matches concept_map Set<V, V> { bool contains(const V& s, const V& v) { return s == v; } }
Specifically, I've used my is_callable to emulate the Callable concept in the enable_if of the contains() overload for functions, and the disable_if in the fallback version.
Thanks, that's very beautiful code. I summarize as: this sort of introspection is still useful for providing concept mappings. That makes sense, thanks. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Hi, The new, powerful way to use enable_if in C++0x might be of interest too: http://lists.boost.org/Archives/boost/2011/04/180082.php. Kind regards, Jeroen

on Sun Apr 01 2012, Jeroen Habraken <vexocide-AT-gmail.com> wrote:
Hi,
The new, powerful way to use enable_if in C++0x might be of interest too: http://lists.boost.org/Archives/boost/2011/04/180082.php.
Absolutely; Matt Calabrese's discovery is an important one. Thanks for the reminder. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 3/31/2012 7:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
I recall a discussion about processing string literals at compile time using user-defined literals. Surely that counts. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On 04/01/2012 06:36 PM, Eric Niebler wrote:
On 3/31/2012 7:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
I recall a discussion about processing string literals at compile time using user-defined literals. Surely that counts.
Not sure if they didn't remove that feature in the end. However, with constexpr you can just do template<BOOST_PP_ENUM_PARAMS(256, char BOOST_PP_INTERCEPT)> struct string; #define CSTRING(s) string<BOOST_PP_ENUM(256, CSTRING_, s)> #define CSTRING_(z,i,s) (i < strlen(s) ? s[i] : '\0') CSTRING("foo") will expand to string<'f', 'o', 'o', '\0', '\0', ...>

On 01.04.2012, at 21:01, Mathias Gaunard wrote:
On 04/01/2012 06:36 PM, Eric Niebler wrote:
On 3/31/2012 7:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated.
I recall a discussion about processing string literals at compile time using user-defined literals. Surely that counts.
Not sure if they didn't remove that feature in the end.
They did. The template <char... Chars> operator "" syntax is only valid for integer (and I think floating point) literals according to the FDIS. Sebastian

Hi,
On 01.04.2012, at 21:01, Mathias Gaunard wrote:
On 04/01/2012 06:36 PM, Eric Niebler wrote:
On 3/31/2012 7:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated. I recall a discussion about processing string literals at compile time using user-defined literals. Surely that counts. Not sure if they didn't remove that feature in the end. They did. The template<char... Chars> operator "" syntax is only valid for integer (and I think floating point) literals according to the FDIS.
It was me writing about it and we ended up using constexpr functions to achieve the same goal - I sent our solution to this list as well. One can write: MPLLIBS_STRING("This is cool") which expands to the definition of a boost::mpl::string. To make usage of it easier, we created an "alias" for MPLLIBS_STRING called _S, so one could write: _S("This is cool") Our implementation can be found here: https://github.com/sabel83/mpllibs/blob/master/mpllibs/metaparse/string.hpp It is an important part of the Mpllibs/Metaparse library I'm going to present on C++Now. It is a C++11-only solution for template metaprogramming, so I think it could be a great addition to an overview about that. Regards, Ábel

on Sun Apr 01 2012, Abel Sinkovics <abel-AT-elte.hu> wrote:
Hi,
On 01.04.2012, at 21:01, Mathias Gaunard wrote:
On 3/31/2012 7:12 PM, Dave Abrahams wrote:
Hi All,
I am on the C++Now 2012 schedule giving a talk on metaprogramming in C++11, which is really just supposed to be an overview of the state of the art. I am just at the beginnings of my research for this presentation, having learned a few things and done a few experiments, and it seemed to me foolish not to ask the Boost community for its insights. I'm sure y'all have come up with many neat tricks and techniques. If you'd care to share them here, that would be much appreciated. I recall a discussion about processing string literals at compile time using user-defined literals. Surely that counts. Not sure if they didn't remove that feature in the end. They did. The template<char... Chars> operator "" syntax is only valid for integer (and I think floating point) literals according to
On 04/01/2012 06:36 PM, Eric Niebler wrote: the FDIS.
It was me writing about it and we ended up using constexpr functions to achieve the same goal - I sent our solution to this list as well. One can write:
MPLLIBS_STRING("This is cool")
which expands to the definition of a boost::mpl::string. To make usage of it easier, we created an "alias" for MPLLIBS_STRING called _S, so one could write:
_S("This is cool")
Our implementation can be found here: https://github.com/sabel83/mpllibs/blob/master/mpllibs/metaparse/string.hpp It is an important part of the Mpllibs/Metaparse library I'm going to present on C++Now.
It is a C++11-only solution for template metaprogramming, so I think it could be a great addition to an overview about that.
Definitely. An excellent point. I don't suppose one can #include a file inside a string literal somehow? ;-) _S(" #include "metaprogram" ") -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On 03/04/12 19:39, Dave Abrahams wrote:
I don't suppose one can #include a file inside a string literal somehow? ;-)
_S(" #include "metaprogram" ")
Assuming your metaprogram is a set of valid C++ tokens, you could do something like #define myprogram some code here _S(STRINGIZE(myprogram))
participants (13)
-
Abel Sinkovics
-
Christopher Jefferson
-
Dave Abrahams
-
Eric Niebler
-
Howard Hinnant
-
Jeroen Habraken
-
Mathias Gaunard
-
Nathan Ridge
-
Olivier Grant
-
paul Fultz
-
Pyry Jahkola
-
Sebastian Redl
-
Sumant Tambe