Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A function that accepts only compile time known expressions?

Compile time expressions are good because you can use them to specialize templates. So for example, tuples can be accessed by using a compile time expression with the std::get method.

std::cout << std::get<0>(my_tuple) << std::endl;

Now, the above expression is pretty ugly. I am trying to develop some sort of tuples myself (hoping to make it to turn them into compile time dictionaries), so that, say, they expose a method in the form:

my_dict.get<0>();

Now, what I would like to do is to substitute that with a [] operator. I was wondering if that was even possible at all. First of all, I wouldn't know how to select only constant, compile time known expressions as parameters for my operator. Moreover, the return type would depend on the value of the constant expression.

With a define, however, I can get closer to what I want with something like

#define item(x) get<x>()

so that I can then use

my_dict.item(0)

Is there a way to get something better than this?

like image 430
Matteo Monti Avatar asked May 30 '15 17:05

Matteo Monti


1 Answers

This approach uses types to convey the index, which are then passed to operator[], which extracts the index.

template<std::size_t n>
using idx_t=std::integral_constant<std::size_t, n>;
template<std::size_t n>
idx_t<n> idx;

constexpr int square( int x ) { return x*x; }
constexpr int power( int base, size_t pow ) {
  return (pow==0)?1:
    (pow==1)?base:
      (
        square(power(base, pow/2))
          *( (pow%2)?base:1 )
      );
}

template<char... cs>
struct helper:idx_t<0>{};
template<char c0, char...cs>
struct helper<c0, cs...>:idx_t< (c0-'0') * power(10, sizeof...(cs)) + helper<cs...>{} > {};

template<char...cs>
constexpr idx_t< helper<cs...>{} > operator""_idx() { return {}; }

struct foo {
  template<std::size_t n>
  void operator[](idx_t<n>) const {
    char arr[n];
    std::cout << sizeof(arr) << '\n';
  }
};

There are 3 (equivalent, up to syntactic sugar) ways to use this:

foo f;
f[idx_t<1>{}];
f[idx<2>];
f[3_idx];
f[1337_idx];

live example. Support for 0xff_idx etc is left as an exercise.

like image 154
Yakk - Adam Nevraumont Avatar answered Oct 05 '22 12:10

Yakk - Adam Nevraumont