I'd like to create a type with a compile-time guarantee that instances are one of N possible values. The values are int types. No arithmetic needed.
One possible solution is to use an enum class, but this scales poorly with N.
I think the solution would look most like a fixed range int. I imagine the usage would look something like this, but i'm not too sure how to implement this.Is something like this possible or am I limited to enum classes?
constexpr auto N = 60;
MyType<N> foo(30); // okay
MyType<N> foo(0); // okay
MyType<N> foo(59); // okay
MyType<N> bar(60); // compile error
MyType<N> boo(-1); // compile error
I don't think it's possible to get compile error, however you can limit it using custom class something like this:
#include <stdexcept>
class MyIntger {
public:
MyIntger(int num){
if(num < Min || num > Max){
throw std::runtime_error("Number out of range");
}
value = num;
}
private:
int value;
const static int Min = 0;
const static int Max = 60;
};
int main(){
MyIntger a(5); // OK
MyIntger b(61); // Throws std::runtime_error
}
You can have compile-time ints in C++ (and thus compile-time limit checking), but syntax is not the same as for runtime ints:
#include <type_traits>
template<size_t N>
struct MyInteger
{
// you might have it as T or limit it to size_t
template<typename T, T I>
MyInteger(std::integral_constant<T, I>)
: value(I) { static_assert(I < N); }
size_t value;
};
int main()
{
MyInteger<60> a(std::integral_constant<size_t, 59>()); // ok
MyInteger<60> b(std::integral_constant<size_t, 60>()); // error
}
If you don't like the long name, you can always have a template type alias, e.g.:
template<size_t K>
std::integral_constant<size_t, K> I = {};
int main()
{
MyInteger<60> a(I<59>);
}
Related
I am looking for a convenient to create a C++ class where some member variables are only present if a template flag is set. As a simple example, let's assume I want to toggle an averageSum in an performance sensitive calculation, i.e.
struct Foo {
// Some data and functions..
void operator+=(const Foo& _other) {}
};
template<bool sumAverages>
class Calculator {
public:
// Some member variables...
// Those should only be present if sumAverages is true
int count = 0;
Foo resultSum;
void calculate(/* some arguments */) {
// Calculation of result...
Foo result;
// This should only be calculated if sumAverages is true
++count;
resultSum += result;
// Possibly some post processing...
}
};
One way would be using preprocessor defines, but those are rather inconvenient especially if I need both versions in the same binary. So I am looking for an alternative using templates and if constexpr and something like the following Conditional class:
template<bool active, class T>
struct Conditional;
template<class T>
struct Conditional<true, T> : public T {};
template<class T>
struct Conditional<false, T> {};
My first shot was this:
template<bool sumAverages>
class Calculator {
public:
int count = 0;
Conditional<sumAverages, Foo> resultSum;
void calculate(/* some arguments */) {
Foo result;
if constexpr(sumAverages) {
++count;
resultSum += result;
}
}
};
The if constexpr should incur no run time cost and as it is dependent on a template variable should allow non-compiling code in the false case (e.g. in this example Conditional<false, Foo> does not define a += operator, still it compiles). So this part is more or less perfect. However the variables count and resultSum are still somewhat present. In particular, as one can not derive from a fundamental type, the Conditional class does not allow to toggle the int dependent on the template. Furthermore every Conditional<false, T> variable still occupies one byte possibly bloating small classes. This could be solvable by the new [[no_unique_address]] attribute, however my current compiler chooses to ignore it in all my tests, still using at leas one byte per variable.
To improve things I tried inheriting the variables like this
struct OptionalMembers {
int count;
Foo resultSum;
};
template<bool sumAverages>
class Calculator : public Conditional<sumAverages, OptionalMembers> {
public:
void calculate(/* some arguments */) {
Foo result;
if constexpr(sumAverages) {
++OptionalMembers::count;
OptionalMembers::resultSum += result;
}
}
};
This should come at no space cost as inheriting from am empty class should do literally nothing, right? A possible disadvantage is that one cannot freely set the order of the variables (the inherited variables always come first).
My questions are:
Do you see any problems using the approaches described above?
Are there better options to de(activate) variables like this?
There are a different ways to solve this, one straightforward one would be using template specialization:
#include <iostream>
template <bool b> struct Calculator {
int calculate(int i, int j) { return i + j; }
};
template <> struct Calculator<true> {
int sum;
int calculate(int i, int j) { return sum = i + j; }
};
int main(int argc, char **argv) {
Calculator<false> cx;
cx.calculate(3, 4);
/* std::cout << cx.sum << '\n'; <- will not compile */
Calculator<true> cy;
cy.calculate(3, 4);
std::cout << cy.sum << '\n';
return 0;
}
Another solution would be to use mixin-like types to add features to your calculator type:
#include <iostream>
#include <type_traits>
struct SumMixin {
int sum;
};
template <typename... Mixins> struct Calculator : public Mixins... {
int calculate(int i, int j) {
if constexpr (is_deriving_from<SumMixin>()) {
return SumMixin::sum = i + j;
} else {
return i + j;
}
}
private:
template <typename Mixin> static constexpr bool is_deriving_from() {
return std::disjunction_v<std::is_same<Mixin, Mixins>...>;
}
};
int main(int argc, char **argv) {
Calculator<> cx;
cx.calculate(3, 4);
/* std::cout << cx.sum << '\n'; <- will not compile */
Calculator<SumMixin> cy;
cy.calculate(3, 4);
std::cout << cy.sum << '\n';
return 0;
}
I just want to ask if there are any uses for passing variables in cpp as template arguments
template<int a> struct foo {
int x = a;
};
int main() {
foo<2> bar;
std::cout << bar.x;
}
Something like this compiles, works and cout's 2 but the same thing can be done by doing
struct foo {
int x;
foo(int a) : x(a) {}
};
int main() {
foo bar(2);
std::cout << bar.x;
}
So what is the point of using variables in template arguments? I can also see a big flaw in using the first method: the variable a uses memory and isn't destructed after x is changed, as it would be after the constructor is called in the second example. It might be helpful if you showed some reasonable uses for that.
When you pass a variable through a template argument, it can be used in compile time.
For example, if you need to create a statically sized array in your class, you could use the template argument to pass the size of your array:
template <int TSize>
class Foo {
[...] // Do whatever you need to do with mData.
private:
std::array<int, TSize> mData;
};
There are many uses for constants in template parameters.
Static Sizes
This is how you would start implementing something like a std::array.
template <typename T, size_t SIZE>
struct Array {
T data[SIZE];
}
Template parameters are always usable in a constexpr context, so they can be used as sizes for statically sized arrays.
Providing Compile-Time Parameters to Algorithms
Another use is parametrizing algorithms like in the following code sample.
We have a uint32_t in ARGB order but to store it in a file, we might need to reorder it to BGRA or RGBA. We know the order at compile time, so we could use an ArgbOrder template variable.
enum class ArgbOrder { ARGB, RGBA, BGRA };
struct ChannelOffsets {
unsigned a;
unsigned r;
unsigned g;
unsigned b;
};
// and we can get a constexpr lookup table from this enum
constexpr ChannelOffsets byteShiftAmountsOf(ArgbOrder format)
{
...
}
template <ArgbOrder order>
void encodeArgb(uint32_t argb, uint8_t out[4])
{
// We can generate the shift amounts at compile time.
constexpr detail::ChannelOffsets shifts = shiftAmountsOf(order);
out[0] = static_cast<u8>(argb >> shifts.a);
out[1] = static_cast<u8>(argb >> shifts.r);
out[2] = static_cast<u8>(argb >> shifts.g);
out[3] = static_cast<u8>(argb >> shifts.b);
}
void example() {
encodeArgb<ArgbOrder::BGRA>(12345);
}
In this example, we can select the appropriate lookup table at compile time and have zero runtime cost. All that needs to happen at runtime is 4 shifts.
Feature Toggles
We can use bool template variables to toggle features in our code, like for example:
template <bool handleZeroSpecially>
int div(int x, int y) {
if constexpr (handleZeroSpecially) {
return y == 0 ? 0 : x / y;
}
else {
return x / y;
}
}
I'm not sure why the array creation in the function passes but not the one in the class even though array size is a compile time computable value.
template<int N>
int getPow()
{
int power = 1;
while(power < N)
power <<= 1;
return power;
}
template<int N>
class Test
{
private:
int data[getPow<N>()];
};
void testfun()
{
int test[getPow<2>()]; // passes
Test<10> t1; // Fails????
}
As getPow is not constexpr, it cannot be used in places which require constant expression (as C-array size).
int test[getPow<2>()]; // passes
. You unfortunately use VLA extension. It should not pass.
You might solve your issue with:
template <unsigned N>
constexpr unsigned getPow()
{
return 1 << N;
}
I am trying to make a simple LookUpTable based on an array of integers, where the idea is to have it calculated at compile time.
Trying to make it possible to use it for any other future tables of various integer types I might have, I need it as a template.
So I have a LookUpTable.h
#ifndef LOOKUPTABLE_H
#define LOOKUPTABLE_H
#include <stdexcept> // out_of_range
template <typename T, std::size_t NUMBER_OF_ELEMENTS>
class LookUpTableIndexed
{
private:
//constexpr static std::size_t NUMBER_OF_ELEMENTS = N;
// LookUpTable
T m_lut[ NUMBER_OF_ELEMENTS ] {}; // ESSENTIAL T Default Constructor for COMPILE-TIME INTERPRETER!
public:
// Construct and Populate the LookUpTable such that;
// INDICES of values are MAPPED to the DATA values stored
constexpr LookUpTableIndexed() : m_lut {}
{
//ctor
}
// Returns the number of values stored
constexpr std::size_t size() const {return NUMBER_OF_ELEMENTS;}
// Returns the DATA value at the given INDEX
constexpr T& operator[](std::size_t n)
{
if (n < NUMBER_OF_ELEMENTS)
return m_lut[n];
else throw std::out_of_range("LookUpTableIndexed[] : OutOfRange!");
}
constexpr const T& operator[](std::size_t n) const
{
if (n < NUMBER_OF_ELEMENTS)
return m_lut[n];
else throw std::out_of_range("LookUpTableIndexed[] const : OutOfRange!");
}
using iterator = T*;
// Returns beginning and end of LookUpTable
constexpr iterator begin() {return &m_lut[0 ];}
constexpr iterator end () {return &m_lut[NUMBER_OF_ELEMENTS];}
};
#endif // LOOKUPTABLE_H
And I'm trying to use it in a class for rapid attenuation of an integer signal wrt an integer distance.
eg. This is just a sample usage as Foo.h
#ifndef FOO_H
#define FOO_H
#include <limits> // max, digits
#include <stdlib.h> // abs
#include "LookUpTable.h" // LookUpTableIndexed
class Foo
{
private:
template <typename TDistance,
TDistance MAXIMUM_DISTANCE,
std::size_t NUMBER_OF_DIGITS>
struct DistanceAttenuation
{
private:
// Maximum value that can be held in this type
//constexpr auto MAXIMUM_DISTANCE = std::numeric_limits<TDistance>::max();
// Number of bits used by this type
//constexpr auto NUMBER_OF_DIGITS = std::numeric_limits<TDistance>::digits;
// LookUpTable
LookUpTableIndexed<TDistance, NUMBER_OF_DIGITS> m_attenuationRangeUpperLimit {}; // ESSENTIAL LookUpTable Default Constructor for COMPILE-TIME INTERPRETER!
// Returns the number of bits to BIT-SHIFT-RIGHT, attenuate, some signal
// given its distance from source
constexpr std::size_t attenuateBy(const TDistance distance)
{
for (std::size_t i {NUMBER_OF_DIGITS}; (i > 0); --i)
{
// While distance exceeds upper-limit, keep trying values
if (distance >= m_attenuationRangeUpperLimit[i - 1])
{
// Found RANGE the given distance occupies
return (i - 1);
}
}
throw std::logic_error("DistanceAttenuation::attenuateBy(Cannot attenuate signal using given distance!)");
}
public:
// Calculate the distance correction factors for signals
// so they can be attenuated to emulate the the effects of distance on signal strength
// ...USING THE INVERSE SQUARE RELATIONSHIP OF DISTANCE TO SIGNAL STRENGTH
constexpr DistanceAttenuation() : m_attenuationRangeUpperLimit {}
{
//ctor
// Populate the LookUpTable
for (std::size_t i {0}; (i < NUMBER_OF_DIGITS); ++i)
{
TDistance goo = 0; // Not an attenuation calculation
TDistance hoo = 0; // **FOR TEST ONLY!**
m_attenuationRangeUpperLimit[i] = MAXIMUM_DISTANCE - goo - hoo;
}
static_assert((m_attenuationRangeUpperLimit[0] == MAXIMUM_DISTANCE),
"DistanceAttenuation : Failed to Build LUT!");
}
// Attenuate the signal, s, by the effect of the distance
// by some factor, a, where;
// Positive contribution values are attenuated DOWN toward ZERO
// Negative UP ZERO
constexpr signed int attenuateSignal(const signed int s, const int a)
{
return (s < 0)? -(abs(s) >> a) :
(abs(s) >> a);
}
constexpr signed int attenuateSignalByDistance(const signed int s, const TDistance d)
{
return attenuateSignal(s, attenuateBy(d));
}
};
using SDistance_t = unsigned int;
constexpr static auto m_distanceAttenuation = DistanceAttenuation<SDistance_t,
std::numeric_limits<SDistance_t>::max(),
std::numeric_limits<SDistance_t>::digits>();
public:
Foo() {}
~Foo() {}
// Do some integer foo
signed int attenuateFoo(signed int signal, SDistance_t distance) {return m_distanceAttenuation::attenuateSignalByDistance(signal, distance);}
};
#endif // FOO_H
I have tried to do this several ways, using the youtube video tutorial by CppCon 2015: Scott Schurr “constexpr: Applications" and others, but it won't compile giving the error;
error: 'constexpr static auto m_distanceAttenuation...' used before its definition
and the static asserts fail with
error: non-constant condition for static assertion
indicating it isn't calculating anything at compile-time.
I'm new to C++.
I know I'm doing something obvious but I don't know what it is.
Am I misusing static or constexpr?
numeric_limits are constexpr?
What am I doing wrong?
Thank you.
Some observations
1) as observed by michalsrb, Foo isn't complete when you initialize m_distanceAttenuation and DistanceAttenuation is part of Foo, so is incomplete.
Unfortunately you can't initialize a static constexpr member with an incomplete type (as better explained by jogojapan in this answer).
Suggestion: define DistanceAttenuation it outside (and before) Foo; so it's a complete type and can be used to initialize m_distanceAttenuation; something like
template <typename TDistance,
TDistance MAXIMUM_DISTANCE,
std::size_t NUMBER_OF_DIGITS>
struct DistanceAttenuation
{
// ...
};
class Foo
{
// ...
};
2) in C++14, a constexpr method isn't a const method; suggestion: define the following method as const too or you can't use they in some constexpr expressions
constexpr std::size_t attenuateBy (const TDistance distance) const
constexpr signed int attenuateSignal(const signed int s, const int a) const
constexpr signed int attenuateSignalByDistance(const signed int s, const TDistance d) const
3) in attenuateBy(), the test in the following for is ever true
for (std::size_t i {NUMBER_OF_DIGITS - 1}; (i >= 0); --i)
because a std::size_t is ever >= 0, so the for goes in loop and never exit; suggestion: redefine i as int or long
4) in attenuateFoo() you use m_DistanceAttenuation where the variable is defined as m_distanceAttenuation; suggestion: correct che name of the variable used
5) in attenuateFoo() you call the method attenuateSignalByDistance() using the :: operator; suggestion: use the . operator, so (considering point (4) too)
signed int attenuateFoo(signed int signal, SDistance_t distance)
{return m_distanceAttenuation.attenuateSignalByDistance(signal, distance);}
I want to calculate factorial at the compile-time. I found some way to solve the problem, but I want to know if there any another solution for this problem without using enum s. Here the solution using enum s.
#include <iostream>
template <int n>
struct fact
{
enum{value = n*fact<n-1>::value};
};
template<>
struct fact<1>
{
enum{value = 1};
};
int main()
{
std::cout << fact<10>::value;
}
If there is no another solution, please describe why the enum s are must.
While there are alternative notations, It's written that way because more compilers accept that enum-style notation. The language supports const integral-type class members with an inline initialization, but some compilers aren't compliant with the standard in that regard. On compilers that are compliant in this regard, the following works just fine:
#include <iostream>
template <unsigned int n>
struct fact
{
static const unsigned int value = n*fact<n-1>::value;
};
template<>
struct fact<0>
{
static const unsigned int value = 1;
};
int main()
{
std::cout << fact<10>::value << "\n";
}
Replace,
enum{value};
with,
static int const value; // or unsigned int
enums are must because they suppose to be resolved at compile time. Which assures that whatever result you calculated must have been done at compile time. Other such type is static int const (means any integral type).
To illustrate:
enum E {
X = strlen(s); // is an error, because X is a compile time constant
};
Alternatively, you can use static const members:
template <unsigned int n>
struct fact { static const unsigned int value = n * fact<n-1>::value; }