$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] Static constexpr map (was: Re: [gsoc16] Can I quickly check if the below really is the best approach?)
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2016-01-17 16:51:06
On 14 Jan 2016 at 13:02, Gottlob Frege wrote:
I had a crack this weekend at a toy static_map to see if I could 
improve on Louis' toy solution from 
https://gist.github.com/ldionne/f7ff609f00dc7025a213. I learned many 
very interesting things.
> Possibly due to limitations with pre-11 C++, I had a two-step process
> for declaring/defining the map:
It turns out this restriction remains in C++ 14, and currently C++ 
17. The problem is that nested braced init of heterogeneous types is 
basically only possible via a C array, so either you do this:
constexpr std::pair<int, const char *> map_data[] = {
  { 5, "apple" },
  { 8, "pear" },
  { 0, "banana" }
};
constexpr auto cmap = make_static_map(map_data);
... or you do as Louis did:
constexpr auto cmap = make_static_map(
  std::make_pair(5, "apple"),
  std::make_pair(8, "pear"),
  std::make_pair(0, "banana")
);
I personally think the first form looks nicer. If C++ 17 could gain 
the ability to convert nested braced init sequences of heterogeneous 
types in a set of nested std::make_tuple()'s, I think that would be a 
great language addition for C++ 17.
> Constexpr probably gets rid of many of those problems.
Unfortunately, constexpr as currently implemented by at least clang 
3.7 and VS2015 is lazy not greedy, so currently even if all the 
inputs to a constexpr expression are constexpr but the returned value 
is not stored constexpr, right now the expression is not executed 
constexpr by any major compiler. In code:
  // No output in assembler, so constexpr except on GCC 5.3
  constexpr auto cmap = make_static_map(map_data);
  // No abort() appears in assembler except on GCC 5.3, so this
  // was executed constexpr
  if(!cmap[8]) abort();
  // This however does cause code implementing a lookup to be 
generated
  // on all compilers, so this was NOT executed constexpr. The cause 
is
  // storing the result in a non-constexpr variable.
  const char *foo=cmap[5];
If you'd like to play with this yourselves, see 
https://goo.gl/eO7ooa.
I was not aware of that constexpr is currently implemented lazy not 
greedy before, and I still find it a highly surprising choice to not 
avail of an optimisation. GCC is particularly conservative in not 
making use of constexpr execution at all, even VS2015 matches clang 
3.7.
Note that the C++ standard, in so far as I can tell, gives compiler 
implementors the choice of what to do if the results from a constant 
expression are not used in a constant expression - they can either 
execute constexpr, or not. I therefore assume the compiler vendors 
have good reasons for choosing to generate code when the standard 
says they don't have to.
Niall
-- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/