Friday, 23 October 2015

Switch() Statement for Types in C++


I saw this question on Stack Overflow some times ago, it amounted to emulating a switch() statement in template code. Then recently I saw a nice example of doing this.

First, the oldskool style, using Boost and C++98:
  template <int N>
  struct shortest_fitting_int
  {
    BOOST_STATIC_ASSERT(N > 0);
    BOOST_STATIC_ASSERT(N <= sizeof(int64_t));
 
    typedef
      typename boost::conditional< (N <= sizeof(int8_t)),
        int8_t,
        typename boost::conditional< (N <= sizeof(int16_t)),
          int16_t,
          typename boost::conditional< (N <= sizeof(int32_t)),
            int32_t,
            int64_t
          >::type
        >::type
      >::type type;
  };
Note the the usage of BOOST_STATIC_ASSERT() and the ubiqutous ::type suffix!

Now have a look at the "modern" C++11 style:
  template <int N>
  struct shortest_fitting_int
  {
    static_assert(N > 0, "negative N");
    static_assert(N <= sizeof(int64_t), "N > 8");
 
    typedef
      std::conditional_t< (N <= sizeof(int8_t)),
        int8_t,
        std::conditional_t< (N <= sizeof(int16_t)),
          int16_t,
          std::conditional_t< (N <= sizeof(int32_t)),
            int32_t,
            int64_t
          >
        >
      > type;
  };
Did you notice how much more readable the code is? The small, innocent-looking C++11 innovation of using XXX_t templates (like void_t, enable_if_t and their ilk) removes so much of clutter! Nice one!

Source: Andrzej's C++ blog: Handling short codes — part I.

Friday, 16 October 2015

Cool usecase for std::tie()


Until now I only thought of std::tie()as useful for decomposing several return values of a function that is faking multiple return values by using std:tuple:
  bool a; 
  SomeData b; 

  std:tie(a, b) = get_a_b_as_tuple();
But now look at that:
  structS 
  {
    int n;
    std::string s;
    float d;

    bool operator<(const S& rhs) const {
      // compares n to rhs.n,
      // then s to rhs.s,
      // then d to rhs.d
      return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d);
    }
  };
Nice, isn't it?

Source: CppCon2015 / Presentations / Simple Extensible Pattern Matching With C++14.

Update:
As it seems, this technique is considered to be pretty standard now, look here. If you are interested in TMP (and param pack expansions ;) you'll find there some techniques to make such comparators more flexible.