Re: C++ Template Metaprogramming - factorial example
I wrote:
I recently purchased David Abrahams' and Aleksey Gurtovoy's new book on the MPL, "C++ Template Metaprogramming" (obviously recently since it's only been out a couple of weeks), and am working through some of the examples. I'm having trouble with the factorial example in section 8.3.1, page 160:
#include
#include #include #include #include #include namespace mpl = boost::mpl;
template <class N> struct factorial : mpl::eval_if< mpl::equal_to
> // check N == 0 , mpl::int_<1> // 0! == 1 , mpl::multiplies< // N! == N * (N-1)! N , factorial > > { BOOST_STATIC_ASSERT(N::value >= 0); // for nonnegative N }; There's a minor issue in that equal.hpp is (apparently) mistakenly included instead of equal_to.hpp, but even after fixing that, I can't get this to compile in the form in which it's written. Should it, or is it broken?
After spending some more time on this I now believe the code is broken.
There's some uncertainty because mpl::multiplies<> has apparently been
either renamed or replaced with mpl::times<>, and only the latter is
documented in the MPL Reference Manual, so I'm not certain whether or
not the two behave identically. However changing "multiplies" to
"times" didn't seem to make any difference in terms of the compilation
errors, so in the analysis that follows I'm making the assumption that
if there is any difference, it isn't doesn't change anything relevant
to the problem at hand.
According to the MPL Reference Manual, in an expression of the form
mpl::times
Brad Austin wrote:
I wrote:
I recently purchased David Abrahams' and Aleksey Gurtovoy's new book on the MPL, "C++ Template Metaprogramming" (obviously recently since it's only been out a couple of weeks), and am working through some of the examples. I'm having trouble with the factorial example in section 8.3.1, page 160:
#include
#include #include #include #include #include namespace mpl = boost::mpl;
template <class N> struct factorial : mpl::eval_if< mpl::equal_to
> // check N == 0 , mpl::int_<1> // 0! == 1 , mpl::multiplies< // N! == N * (N-1)! N , factorial > > { BOOST_STATIC_ASSERT(N::value >= 0); // for nonnegative N };
With the modified include directive, the code compiles fine for me on GCC (MinGW) 3.2.x, 3.3.x and 3.4.x.
Anyway, is this mailing list an appropriate place to bring up issues like this? I know David and Aleksey are members, but I'm not clear on whether their book qualifies as an official Boost product.
This is as good a place as any to bring up the question. You posted on a weekend; now that it's over you should get an anser soon. Jonathan
Brad Austin writes:
I wrote:
I recently purchased David Abrahams' and Aleksey Gurtovoy's new book on the MPL, "C++ Template Metaprogramming" (obviously recently since it's only been out a couple of weeks), and am working through some of the examples. I'm having trouble with the factorial example in section 8.3.1, page 160:
#include
#include #include #include #include #include namespace mpl = boost::mpl;
template <class N> struct factorial : mpl::eval_if< mpl::equal_to
> // check N == 0 , mpl::int_<1> // 0! == 1 , mpl::multiplies< // N! == N * (N-1)! N , factorial > > { BOOST_STATIC_ASSERT(N::value >= 0); // for nonnegative N }; There's a minor issue in that equal.hpp is (apparently) mistakenly included instead of equal_to.hpp, but even after fixing that, I can't get this to compile in the form in which it's written. Should it, or is it broken?
After spending some more time on this I now believe the code is broken.
You are right.
There's some uncertainty because mpl::multiplies<> has apparently been either renamed or replaced with mpl::times<>, and only the latter is documented in the MPL Reference Manual, so I'm not certain whether or not the two behave identically.
They do. 'multiplies' is simply a synonym for 'times'.
However changing "multiplies" to "times" didn't seem to make any difference in terms of the compilation errors, so in the analysis that follows I'm making the assumption that if there is any difference, it isn't doesn't change anything relevant to the problem at hand.
According to the MPL Reference Manual, in an expression of the form mpl::times
, T1 and T2 must meet the requirements of an integral constant, not merely the weaker requirements of a nullary metafunction.
Correct.
In this case T2 is an expression of the form factorial<T3>, so for this to be vaild factorial<> must model an integral constant, not merely a metafunction *returning* an integral constant.
Ditto.
However factorial<> derives from an expression of the form mpl::eval_if
, and doesn't add any nested types or a value of its own. Therefore factorial<> only models an integral constant if mpl::eval_if does, which it doesn't.
More precisely, it doesn't in the "official" 1.32.0 codebase. In the Boost distribution on the CD 'eval_if' _derives_ from the result metafunction, and that's probably how this and may be a few other factorial examples slipped through our tests. Removal of the inheritance for GCC (as an implementation detail) was a last-minute fix just before 1.32 was officially released.
mpl::eval_if
::type models an integral constant (provided T5:type and T6::type do), but mpl::eval_if is merely a metafunction returning that constant. Also, the first argument to eval_if is supposed to be an integral constant, and T4 is an expression of the form mpl::equal_to
, which again is just a nullary function, not an integral constant.
Not if T7 and T8 are Integral Constants, see http://www.boost.org/libs/mpl/doc/refmanual/equal-to.html. -- Aleksey Gurtovoy MetaCommunications Engineering
participants (3)
-
Aleksey Gurtovoy
-
Brad Austin
-
Jonathan Turkanis