somnium somnium - 10 months ago 47
C++ Question

Idiomatic way to calculate template parameter depending on other parameters

I am looking for an idiomatic way to optimize this template I wrote.

My main concern is how to correctly define the template parameter

and using it as a return parameter while the user must not overwrite it.

I am also open for other suggestions on how to write this template in an idiomatic C++14 way.

typename InType=uint32_t,
typename OutType=float,
unsigned long bits=8,
unsigned long n=(sizeof(InType) * 8) / bits
std::array<OutType,n> hash_to_color(InType in) noexcept {
InType mask = ~0;
mask = mask << bits;
mask = ~mask;
std::array<OutType,n> out;
auto out_max = static_cast<OutType>((1 << bits) - 1);
for (auto i = 0; i < n; i++) {
auto selected = (in >> (i * bits)) & mask;
out[i] = static_cast<OutType>(selected) / out_max;
return out;

Answer Source

Regarding the n template parameter, you can avoid it by using auto as the return type in C++14. Here's a simpler example of the principle:

template<int N>
auto f()
    constexpr int bar = N * 3;   
    std::array<int, bar> foo;
    return foo;

Naturally the calculation of the array template parameter must be a constant expression.

Another option (compatible with C++11) is trailing-return-type:

template<int N>
auto f() -> std::array<int, N * 3>

This is a wee bit more verbose than taking advantage of C++14's allowing of return type deduction from the return statement.

Note: ~0 in your code is wrong because 0 is an int, it should be ~(InType)0. Also (1 << bits) - 1 has potential overflow issues.