Live On Coliru
I need to implement a utility class for the purpose of lookup. The value of the internal array never changes after the initialization. My initial plan was to implement this class with the help of constexpr so that the expensive initialization can be done in compilation time. However, I am not able to come up with a good solution. So far, I can only figure out the following two methods. Both methods have drawbacks.
Method One:
The implementation looks complicate for such a simple task.
Method Two:
First, I assume the initialization is done in compilation time. Is this correct?
Second, the TwoClass::m_array really should be static instead of a member variable.
Is there a better way to implement this with c++20?
Thank you
#include <iostream>
#include <array>
using namespace std;
//== Method One
class OneClass
{
public:
uint32_t get(size_t index)
{
return m_array[index % 0xFF];
}
struct init_static_array
{
init_static_array()
{
// std::cout << "call init_static_array\n";
for (int i = 0; i < N; i++) {
m_array[i] = i * i + 10;
}
}
};
private:
static init_static_array m_init_static_array;
enum {N = 255};
static int m_array[N]; // this is a lookup table and NEVER will be changed!
};
int OneClass::m_array[] = {0};
OneClass::init_static_array OneClass::m_init_static_array{};
//== Method Two
class TwoClass
{
public:
constexpr TwoClass()
{
//std::cout << "call TwoClass::TwoClass()\n";
for (int i = 0; i < N; i++) {
m_array[i] = i * i + 10;
}
}
int get(size_t index) const
{
return m_array[index % 0xFF];
}
private:
enum {N = 255};
int m_array[N] {0}; // this is a lookup table and NEVER will be changed!
};
int main()
{
OneClass oneclass;
cout << "1 => " << oneclass.get(1) << std::endl;
cout << "256 => " << oneclass.get(256) << std::endl;
cout << "==================\n";
TwoClass twoclass;
cout << "1 => " << twoclass.get(1) << std::endl;
cout << "256 => " << twoclass.get(256) << std::endl;
return 0;
}
Output:
call init_static_array
1 => 11
256 => 11
==================
call TwoClass::TwoClass()
1 => 11
256 => 11
If it's C++20, don't you just want this:
namespace {
constexpr std::size_t N{255u};
consteval std::array<int, N> initArr()
{
std::array<int, N> arr{};
for (int i = 0; i < N; i++) {
arr[i] = i * i + 10;
}
return arr;
}
}
class C
{
private:
constexpr static std::array<int, N> arr{initArr()};
public:
constexpr C() = default;
int get(std::size_t n) const {return arr[n%255];}
};
Neither of your methods initialized the array at compile-time.
In the first method, the array is initialized in construction of static data member m_init_static_array, e.g. before main is called.
In the second method, constexpr in function declarations, including constructors, indicates that you want them being able to be called at compile-time, e.g. in evaluation of constant expressions. It doesn't mean all invocations are evaluated at compile-time. To call constexpr functions as compile-time, you have to call them in constant expression.
One solution is to initialize the static constexpr data member internal_array of type std::array by a lambda:
#include <array>
class Demo {
public:
int get(int index) const {
return internal_array[index % N];
}
private:
static inline constexpr int N = 255;
static inline constexpr std::array<int, N> internal_array = []() {
// Cannot call non-constexpr functions at compile-time
// std::cout << "std::cout << "call init_static_array\n";
std::array<int, N> arr;
for (int i = 0; i < N; ++i)
arr[i] = i * i + 10;
return arr;
}();
};
int main() {
Demo demo;
return demo.get(10);
}
Related
I have an external function defined as
extern "C" int64_t ASMFunction(int64_t sort);
Then I have a C++ function defined like this:
template <typename T>
void results(T&& sort) {
ASMFunction([&](int64_t sort[60]) {for (int i = 0; i < sizeof(sort); i++) {
sort[i] = rand() % 9223372036854775807;
};
return sort; }
);
}
The reason I define it under a template is because otherwise I get the compiler error no suitable conversion function from "lambda []int64_t *(int64_t *sort)->int64_t *" to "int64_t" exists. Otherwise, I wouldn't even have the separate function to call my external ASMFunction, but would just do it in main(). With that, I get the compiler error Error C2664 'int64_t ASMFunction(int64_t)': cannot convert argument 1 from 'main::<lambda_2b1e6f6fde7359a6cb4cb68639dfae02>' to 'int64_t'. How can I use the C++ Lambda function to generate an array of random integers as a parameter for another function?
You are trying to generate a list of numbers, but your ASMFunction only gets one.
If you want a list you can do this:
int64_t ASMFunction(int64_t * sort)
{
std::cout << "Num: " << sort[1] << endl;
return 0;
}
template <typename T, const int64_t N>
void results(T (&sort)[N]) {
ASMFunction([&]() {for (int64_t i = 0; i < N; i++) {
sort[i] = rand() % 9223372036854775807;
};
return sort;
}() // <- note you are calling the function to generate the list
);
}
int main() {
int64_t i[10];
results(i);
return 0;
}
If you want only one number:
int64_t ASMFunction(int64_t sort)
{
std::cout << "Num: " << sort << endl;
return 0;
}
template <typename T, const int64_t N>
void results(T (&sort)[N]) {
ASMFunction([&]() { return rand() % 9223372036854775807; }() );
}
int main() {
int64_t i[10];
results(i);
return 0;
}
The typename T is the type, in this case int64_t and the const int64_t N is to be able to have the array size deduced by the template.
There will be a new template instance for each array size.
For example, I want to display value of only one member of structure/union array, so I want to pass it as argument into a function that will display only that one member and will also display any other single member that I pass as argument.
#include <iostream>
using namespace std;
union ThreeTypes
{
char letter;
int whole;
double real;
};
void showArr(ThreeTypes[], int); // ?? What parameters to pass?
int main()
{
const int SIZE = 50;
ThreeTypes arr[SIZE];
for (int i = 0; i < SIZE; i++)
arr[i].real = 2.37;
showArr(arr, SIZE, ??? ); // what argument to pass to display member?
return 0;
}
void showArr(ThreeTypes arr[],int size,???) // also, what parameters??
{
for (int i = 0; i < size; i++)
cout << arr[i].?? << endl; // member from argument????
}
One option would be a templated pointer-to-member type. These are usually used with class or struct types, but are also valid with a union type. A pointer-to-member type is declared like MemberType ClassType::*pointer_name, and the name of such a pointer can be used to the right of the .* or ->* operator.
template <typename T>
void showArr(const ThreeTypes arr[], int size, T ThreeTypes::*ptr)
{
for (int i = 0; i < size; ++i)
std::cout << (arr[i].*ptr) << std::endl;
}
And you create a pointer-to-member value with the syntax &ClassType::member_name:
int main()
{
const int SIZE = 50;
ThreeTypes arr[SIZE];
for (int i = 0; i < SIZE; i++)
arr[i].real = 2.37;
showArr(arr, SIZE, &ThreeTypes::real);
}
Another more general option would be to take a callable functor:
template <typename F>
void showArr(const ThreeTypes arr[], int size, const F& func)
{
for (int i = 0; i < size; ++i)
std::cout << func(arr[i]) << std::endl;
}
You can create a functor to access a member using a lambda or std::mem_fn:
void print_reals_twice(const ThreeTypes arr[], int size)
{
showArr(arr, size, [](const ThreeTypes& u) { return u.real; });
// Same effects:
showArr(arr, size, std::mem_fn(&ThreeTypes::real));
}
But defining showArr this way also lets you pass a functor that does something more complicated than just return a member, if you wanted:
void print_sin2x_all(const ThreeTypes arr[], int size)
{
showArr(arr, size, [](const ThreeTypes& u) { return std::sin(2*u.real); });
}
In C++17 you should use std::variant:
using ThreeTypes = std::variant<char, int, double>;
template <std::size_t N>
auto show_arr(std::array<ThreeTypes, N>& arr)
{
for (auto& e : arr)
{
std::visit([](auto e) { std::cout << e << std::endl;}, e);
}
}
auto test()
{
std::array<ThreeTypes, 2> arr = {3.4, 'a'};
show_arr(arr);
}
The first time the function is called it returns 1. Every other time it's called it returns 1+the number returned the last time it was called.
int counter()
{
return counter()++;
}
Is this valid?
Sounds like you want a static variable:
int counter()
{
static int count = 0; // initialized only once across all calls
return ++count;
}
You can use static.
int counter()
{
static int counter = 0;
return ++counter;
}
Static (in the function body context) is just a nice keyword that makes a variable essentially global, but not semantic-wise. So you cannot use it outside of the function, but it gets initialized with all the globals (it means once near the start point) and it is stored where other global variables are.
Just for the record, since c++ label. You could write a functor class, with a private count variable and overload operator(). Or even probably a template that would be able to wrap any function and count its calls.
Also note that in your try, you call counter recursively with no exit point with a fixed value. It will never finish (unless you count stack overflowing as end).
Apart from defining a static local variable in the function as it was already shown you can define a static class member function that will increment a static data member of the same class. For example
#include <iostream>
class Counter
{
public:
static int Count() { return ( ++cnt ); }
static int Reset() { return ( cnt = 0 ); }
private:
static int cnt;
};
int Counter::cnt = 0;
int main()
{
for ( int i = 0; i < 10; i++ ) std::cout << Counter::Count() << ' ';
std::cout << std::endl;
std::cout << "\nResetting the counter to " << Counter::Reset() << std::endl;
for ( int i = 0; i < 10; i++ ) std::cout << Counter::Count() << ' ';
std::cout << std::endl;
}
If using C++11, use a std::function and a mutable lambda expression:
#include <iostream>
#include <functional>
using namespace std;
int main()
{
function<int()> func = [&]()
{
static int i = 1;
return i++;
};
for(int i = 0; i < 10; i++)
cout << func() << endl;
return 0;
}
I have requirement as follows.
I have to generate increment negative numbers from -1 to -100 which is used a unique id for a request. Like it should be like this: -1, -2, -3, ...-100, -1, -2, and so on. How can I do this effectively? I am not supposed to use Boost. C++ STL is fine. I prefer to write simple function like int GetNextID() and it should generate ID. Request sample program on how to do this effectively?
Thanks for your time and help
int ID = -1;
auto getnext = [=] mutable {
if (ID == -100) ID = -1;
return ID--;
};
Fairly basic stuff here, really. If you have to ask somebody on the Interwebs to write this program for you, you should really consider finding some educational material in C++.
I love the functor solution:
template <int limit> class NegativeNumber
{
public:
NegativeNumber() : current(0) {};
int operator()()
{
return -(1 + (current++ % limit));
};
private:
int current;
};
Then, you can define any generator with any limit and use it:
NegativeNumber<5> five;
NegativeNumber<2> two;
for (int x = 0; x < 20; ++x)
std::cout << "limit five: " << five() << "\tlimit two: " << two() << '\n';
You can also pass the generator as parameter to another function, with each funtor with its own state:
void f5(NegativeNumber<5> &n)
{
std::cout << "limit five: " << n() << '\n';
}
void f2(NegativeNumber<2> &n)
{
std::cout << "limit two: " << n() << '\n';
}
f5(five);
f2(two);
If you don't like the template solution to declare the limit, there's also the no-template version:
class NegativeNumberNoTemplate
{
public:
NegativeNumberNoTemplate(int limit) : m_limit(limit), current(0) {};
int operator()()
{
return -(1 + (current++ % m_limit));
};
private:
const int m_limit;
int current;
};
Using as argument to a function works in the same way, and it's internal state is transfered as well:
void f(NegativeNumberNoTemplate &n)
{
std::cout << "no template: " << n() << '\n';
}
NegativeNumberNoTemplate notemplate(3);
f(notemplate);
I hope you don't want to use it with threading, they're not thread safe ;)
Here you have all the examples; hope it helps.
Something like.... (haven't compiled)
class myClass
{
int number = 0;
int GetValue ()
{
return - (number = ((number+1) % 101))
}
}
Even a simple problem like this could lead you to several approximations, both in the algorithmic solution and in the concrete usage of the programming language.
This was my first solution using C++03. I preferred to switch the sign after computing the value.
#include <iostream>
int GetNextID() {
// This variable is private to this function. Be careful of not calling it
// from multiple threads!
static int current_value = 0;
const int MAX_CYCLE_VALUE = 100;
return - (current_value++ % MAX_CYCLE_VALUE) - 1;
}
int main()
{
const int TOTAL_GETS = 500;
for (int i = 0; i < TOTAL_GETS; ++i)
std::cout << GetNextID() << std::endl;
}
A different solution taking into account that the integer modulo in C++ takes the sign of the dividend (!) as commented in the Wikipedia
#include <iostream>
int GetNextID() {
// This variable is private to this function. Be careful of not calling it
// from multiple threads!
static int current_value = 0;
const int MAX_CYCLE_VALUE = 10;
return (current_value-- % MAX_CYCLE_VALUE) - 1;
}
int main()
{
const int TOTAL_GETS = 50;
for (int i = 0; i < TOTAL_GETS; ++i)
std::cout << GetNextID() << std::endl;
}
I would like to implement a Base class with attributes of a size I already know at compile-time. So my idea was to use a template for this Base class. The following code compiles and runs fine under VC++9.0.
Class definition in the .h file
template<int N> class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
// instantiation
template class BaseClass<2>;
template<int N> BaseClass<N>::BaseClass(void)
{
idx = new int [N];
incr= new int [N];
limit = new int[N];
for(int m = 0; m < N; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
template<int N> BaseClass<N>::~BaseClass(void)
{
}
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[N-1]; idx[N-1] < limit[N-1]; idx[N-1] += incr[N-1] )
{
cout << "LoopMethod Nr " << N-1 << " is called." << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass<2> baseObj;
baseObj.LoopMethod();
system("PAUSE");
return 0;
}
Now I want to nest the for-loops from the LoopMethod times the size of the class attributes. I.e. the compiler should generate a code I would write by Hand as
template<int N> void BaseClass<N>::LoopMethod( )
{
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
for( idx[1]; idx[1] < limit[1]; idx[1] += incr[1] )
{
cout << "LoopMethod Nr " << 1 << " is called." << endl;
}
cout << "LoopMethod Nr " << 0 << " is called." << endl;
}
}
Anyway, I can prompt the compiler to do this, if I do not declare the BaseClass to be a template class. The code for this would then look like:
class BaseClass
{
int* idx;
int* incr;
int* limit;
public:
BaseClass(void);
~BaseClass(void);
template<int M> void LoopMethod(void);
};
Implementation of the class methods in the .cpp file
#include "BaseClass.h"
#include<iostream>
using namespace std;
template void BaseClass::LoopMethod<1>();
BaseClass::BaseClass(void)
{
idx = new int [2];
incr= new int [2];
limit = new int[2];
for(int m = 0; m < 2; m++)
{
idx[m] = 0;
incr[m] = 1;
limit[m] = 2;
}
}
BaseClass::~BaseClass(void)
{
}
template<int M> void BaseClass::LoopMethod( )
{
for( idx[M]; idx[M] < limit[M]; idx[M] += incr[M] )
{
cout << "LoopMethod Nr " << M-1 << " is called." << endl;
LoopMethod<M-1>();
}
}
template<> void BaseClass::LoopMethod<0>(void)
{
idx[0] = 0;
for( idx[0]; idx[0] < limit[0]; idx[0] += incr[0] )
{
// do something
cout << "Now the inner loop is executed" << endl;
}
}
Implementation of the main-function:
#include<cstdlib>
#include "BaseClass.h"
using namespace std;
int main()
{
BaseClass baseObj;
baseObj.LoopMethod<1>();
system("PAUSE");
return 0;
}
But the solution I am searching for is to have a template class with a template method “LoopMethod” owing its own template parameter which tells the compiler how many times to nest the for-Loop. I have tried various possibilities but without success. Does anybody have a suggestion or even know a solution for this template problem?
Thanks in advance for your help,
Markus.
There are a lot of issues with your template:
What exactly is the purpose of the whole thing?
Why are you initialising the pointers with new? You know the size at compile time so why not just make them arrays?
You are not deleting the memory you are allocating
Exception safety if new fails for one of the later arrays
Implementation probably should be in the header file unless it is used for very few values of N which you instantiate
Better to use classes that exist that do this kind of thing, eg boost::array
Refactor out various sections of it.
But the solution I am searching for is
to have a template class with a
template method “LoopMethod” owing its
own template parameter which tells the
compiler how many times to nest the
for-Loop
Is that what you are asking:
template<int N>
struct X
{
template<int M>
void loop();
};
template<int N>
template<int M>
void X<N>::loop<M>()
{
}