2

If I am using a C++ class with a template parameter of an int like:

template<int width> class ap_uint { ... }

then I understand that I can create specific definitions from this type of certain widths like:

typedef ap_uint<72> data_t;

However, if I wanted to say define a constant and pass that in, what are my options (other than define)? Say something like this:

#define WIDTH 72
typedef ap_uint<WIDTH> data_t;
typedef ap_uint<WIDTH / 8> mask_t; // Does this even work?

Further would it be possible to define a function or use an existing one in the template parameter selection? Something like this:

#define SIZE 1024
typedef ap_uint<ceil(log(SIZE, 2))> addr_t;

I am fine having to write the functions myself, if that is even possible.

max66
  • 65,235
  • 10
  • 71
  • 111
dagronlund
  • 1,612
  • 3
  • 13
  • 15
  • 3
    The alternaitve to #define are `constexpr` and other template calculations. – john Jul 27 '19 at 20:15
  • Yep, that's possible and called template meta-programming (there are some examples https://en.wikibooks.org/wiki/C%2B%2B_Programming/Templates/Template_Meta-Programming) – J. S. Jul 27 '19 at 20:16
  • Since `ap_uint` takes an `int` as a parameter, [yes](http://cpp.sh/7n2rp). There should be no problem. –  Jul 27 '19 at 20:28

2 Answers2

4

Template arguments must be constant expressions. So your options include #define, enum, const int and constexpr int and expressions/functions that yield constant expressions (specifically constexpr functions). constexpr int is the modern C++ way of doing it.

WIDTH / 8 does work.

In essence it must be a compile-time constant

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • 3
    Constexpr functions were exactly what I was looking for, thanks! https://en.cppreference.com/w/cpp/language/constexpr – dagronlund Jul 27 '19 at 20:24
3

Some observations, in no particular order.

(1) you tagged C++11, so not only typedef but (better, IMHO) also using

using data_t = ap_uint<72>;

(2) you can also "templatize" using

template <int I>
using data_t = ap_uint<I+3>;

(3) "does this even work?"

#define WIDTH 72    
typedef ap_uint<WIDTH / 8> mask_t; 

Works.

But, given that you tagged C++11, I suggest to avoid #define and use a constexpr constant instead

constexpr auto WIDTH = 72;

using mask_t = ap_uint<WIDTH / 8>; 

(4) "would it be possible to define a function or use an existing one in the template parameter selection"

Pre C++11 the answer was: no.

But you tagged C++11 so the answer is: yes, but the function must be a constexpr one

Example

constexpr int foo (int a)
 { return a+3; }

constexpt int bar = 42;

using data_t = ap_uint<foo(bar)>; // compile: foo(bar) is a constant expression

int baz = 42;

using data_t2 = ap_uint<foo(baz)>; // compilation error! baz isn't a constant 
                                   // expression so foo(baz) isn't

(5) std::ceil() and std::log() aren't constexpr so

#define SIZE 1024
typedef ap_uint<ceil(log(SIZE, 2))> addr_t;

doesn't compile

(6) "I am fine having to write the functions myself, if that is even possible."

Starting from C++11 it's possible (see point (4) for an example).

Unfortunately, only starting from C++14 it's possible to write complex constexpr functions.

In C++11, a constexpr function can almost contains only (simplifying a little) a return instruction.

max66
  • 65,235
  • 10
  • 71
  • 111