Glen Fernandes writes:
Dear Boost community,
The formal review of Louis Dionne's Hana library starts Monday, 10th
June and ends on 24th June.
After playing for a few of hours with Hana I take my hat off to Louis
for the impressive feat he accomplished with the library and the
excellent documentation. MPL unlocked a whole new world of C++
programming that few, at the time, suspected existed. I can only hope
that Hana will do the same. But I am not yet certain of it. Maybe it is
due to the heavy paradigm shift which I haven't yet made. In MPL and
Fusion there was a clear distinction between the compile and run-time
worlds (In the former pretty much everything, save for_each, was
compile-time, and in latter all the compile time stuff lived in
result_of namespace ). With Hana that line is fuzzy. I understand that
Louis considers it its big achievement and it may be so but I am not yet
convinced. To me type manipulations (metaprogramming) were always
something that went on between the programmer and the compiler and were
entirely gone from the resulting binary.
Here is a small example that uses an mpl type map and the corresponding
code I put together (likely sub-optimally) using hana:
// hana.cpp
#include <cassert>
#include <string>
#include <array>
#include
#include <iostream>
#ifdef _USE_HANA
#include
#include
#else
#include
#include
#include
#include
#include
#include
#include
#endif
#ifndef _USE_HANA
template
struct make_arr{
typedef std::array<_Type, _Sz::value> type;
};
#else
namespace hana = boost::hana;
using namespace boost::hana::literals;
#endif
void run()
{
static constexpr int map_size = 100;
#ifdef _USE_HANA
constexpr auto hana_range = hana::range(hana::int_<0>,
hana::int_);
auto hana_inserter = [](auto st_, auto el_){
return hana::insert(st_, hana::make_pair(el_,
hana::type>));
};
// create a map of (int_<0>, array)(int_<1>, array),
etc
/*constexpr*/ auto hana_map = hana::fold.left(hana_range,
hana::make_map(), hana_inserter);
// Can I use make_pair() here as a metafunction instead of defining my
own inserter?
#else
typedef mpl::range_c mpl_range;
// create a map of (int_<0>, array)(int_<1>, array),
etc
typedef mpl::transform<
mpl_range
,mpl::pair >
,mpl::inserter, mpl::insert >
::type mpl_map;
#endif
#ifdef _USE_HANA
// find the element at index 69;
/*constexpr*/ auto hana_el_0 = hana_map[hana::int_<69>];
// instantiate the array
constexpr decltype(hana_el_0)::type arr = {0};
static_assert(sizeof(arr, 69), "");
#else
typedef mpl::at>::type mpl_el_0;
constexpr mpl_el_0 arr = {0};
static_assert(sizeof(arr, 69), "");
#endif
}
int main(int argc_, char **argv_)
{
int c = boost::lexical_cast<int>(argv_[1]);
for(int i = 0; i < c; ++i)
run();
}
Despite Louis's claims of a significant compile-time speed up with Hana,
I get the following with clang 3.6.0:
$time clang++ -O3 -D_USE_HANA -stdlib=libc++ -std=c++14 hana.cpp -o
hana
real 0m55.233s
user 0m54.190s
sys 0m0.631s
$time clang++ -O3 -stdlib=libc++ -std=c++14 hana.cpp -o mpl
real 0m2.162s
user 0m1.632s
sys 0m0.108s
And at run-time: (run a loop of 10000)
$ time ./hana 100000
real 0m2.834s
user 0m2.825s
sys 0m0.006s
$ time ./mpl 100000
real 0m0.021s
user 0m0.002s
sys 0m0.001s
Which clearly shows that the stuff intended to be purely compile-time
has leaked into the run-time.
Also it appears that Hana lets the compiler swallow all kinds of code
that doesn't appear to have any practical meaning:
I understand (maybe erroneously) that a hana::map can have a useful
application only if its keys are compile-time constructs, and yet I was
able to compile:
make_map(make_pair(1, "one"), make_pair(2, "two"));
and even
make_map(1,2,3);
It's not at all clear to me how the results of such expressions can be
used.