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);
}
Related
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);
}
I need help... appropriate questions have been asked in the comments. The programs has zero compiler errors and warnings!! I have concerns with calling a member function from another member function using function pointers. (To be precise, setMatrixto() is trying to call setElement() function using function pointer)
Plus somehow the "hello there" is not being printed to the console. I was expecting it to show up as output.Maybe the setMatrixto() is not getting called at all!!
Header File definition
#ifndef MATRIXOPERATIONS_H
#define MATRIXOPERATIONS_H
class MatrixOperations;
typedef int (MatrixOperations::*INTFUNC)(int,int);
typedef void (MatrixOperations::*VOIDFUNC)(int,int,int);
class MatrixOperations
{
public:
MatrixOperations();
MatrixOperations(int size);
~MatrixOperations();
//diagonal matrix funtions
void displayMatrixOf(INTFUNC f);
void setMatrixTo(VOIDFUNC f);
int getElement(INTFUNC from, int i, int j);
void setElement(VOIDFUNC to,int i ,int j, int value);
int fromDiagonalArray(int i, int j);
void toDiagonalArray(int i, int j, int value);
protected:
private:
int size;
int* a;
};
#endif // MATRIXOPERATIONS_H
CPP Implementation File
#include "MatrixOperations.h"
#include <iostream>
using namespace std;
MatrixOperations::MatrixOperations()
{
//ctor
size = 3;
a = new int[size];
}
MatrixOperations::MatrixOperations(int size)
{
//ctor
this->size = size;
a = new int[size];
}
MatrixOperations::~MatrixOperations()
{
//dtor
delete[] a;
}
///////////////////FUCNTION POINTER SECTION///////////////////////////////////
int MatrixOperations::getElement(INTFUNC from, int i, int j)
{
return (this->*from)(i,j);
}
void MatrixOperations::setElement(VOIDFUNC to,int i ,int j, int value)
{
(this->*to)(i,j,value);
}
/////////////////////////////////DIAGONAL ARRAY OPERATIONS/////////////////////////////////////////////////
int MatrixOperations::fromDiagonalArray(int i, int j)
{
if(i==j)
{
return a[i];
}
else
{
return 0;
}
}
void MatrixOperations::toDiagonalArray(int i, int j, int value)
{
a[i] = value;
}
///////////////////////////////////////////////////////////////////
void MatrixOperations::displayMatrixOf(INTFUNC f)
{
for(int i{0}; i < size; i++)
{
for(int j{0}; j < size; j++)
{
cout << getElement(f,i,j) << "\t"; //is this the correct way to send the function pointer?
}
cout << endl;
}
}
void MatrixOperations::setMatrixTo(VOIDFUNC f)
{
cout << "Hello there!!"; //not getting this output.. whats wrong??
for(int i{0}; i < size; i++)
{
int value {};
cout << "Enter value diagonal element " << i << " : ";
cin >> value;
setElement(f,i,i,value); //is this the correct way to send the function pointer?
}
}
///////////////////////////////////////////////////////////////////////////////
Main File
#include <iostream>
#include "MatrixOperations.h"
typedef MatrixOperations MATRIX;
using namespace std;
int main()
{
MATRIX m1;
m1.setMatrixTo(MATRIX::toDiagonalArray); //was expecting a "Hello there!" but i am not getting that output either
return 0;
}
EDIT2: I added all the class definitions and main function in one single file. SURPRISINGLY!! this works . I am confused??!!!
#include <iostream>
using namespace std;
class MatrixOperations;
typedef void (MatrixOperations::*VOIDFUNC)(int,int,int);
typedef MatrixOperations MATRIX;
class MatrixOperations
{
public:
MatrixOperations();
MatrixOperations(int size);
~MatrixOperations();
//diagonal matrix funtions
void setMatrixTo(VOIDFUNC f);
void setElement(VOIDFUNC to,int i ,int j, int value);
void toDiagonalArray(int i, int j, int value);
private:
int size;
int* a;
};
MatrixOperations::MatrixOperations()
{ //ctor
size = 3;
a = new int[size];
}
MatrixOperations::MatrixOperations(int size)
{ //ctor
this->size = size;
a = new int[size];
}
MatrixOperations::~MatrixOperations()
{
//dtor
delete[] a;
}
void MatrixOperations::setElement(VOIDFUNC to,int i ,int j, int value)
{
(this->*to)(i,j,value);
}
/////////////////////////////////DIAGONAL ARRAY OPERATIONS/////////////////////////////////////////////////
void MatrixOperations::toDiagonalArray(int i, int j, int value)
{
a[i] = value;
}
///////////////////////////////////////////////////////////////////
void MatrixOperations::setMatrixTo(VOIDFUNC f)
{
cout << "Hello there!!" << endl;
for(int i{0}; i < size; i++)
{
int value {};
cout << "Enter value diagonal element " << i << " : ";
cin >> value;
setElement(f,i,i,value);
}
}
int main()
{
MATRIX m1;
m1.setMatrixTo(MATRIX::toDiagonalArray);
return 0;
}
There is nothing wrong with the code in both cases. Its just my debugger was not running in admin mode. I got error code 740. So I launched my IDE in admin mode and voila it worked.
In the code below, I have a function where a length parameter must be passed, like this:
int recv(char* buf, int len);
But a convenience is to write a helper function like this:
template <size_t N>
int recv(char(&array)[N]) {
return recv(array, N);
}
Which means you can pass an array and the compiler somehow 'knows' the size so you don't have to pass it.
But when I have used templates before, I needed to pass the type, eg
std::vector<int> myvec;
But how does that work? Internally what is the compiler doing to resolve this? What is the name of this feature?
Please explain the syntax.
#include <string.h>
#include <iostream>
class test_recv
{
public:
test_recv() {
strcpy(arr, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
}
int recv(char* buf, int len) {
int tmp = pos;
while (len-- && pos < 26)
*buf++ = arr[pos++];
return pos - tmp;
}
template <size_t N>
int recv(char(&array)[N]) {
return recv(array, N);
}
private:
int pos = 0;
char arr[26+1];
};
int main() {
test_recv test;
char buffer[10];
int bytes;
while ((bytes = test.recv(buffer, 10)) != 0) {
for (int i = 0; i < bytes; ++i)
std::cout << buffer[i];
}
std::cout << '\n';
test_recv test2;
char buffer2[10];
while ((bytes = test2.recv(buffer2)) != 0) {
for (int i = 0; i < bytes; ++i)
std::cout << buffer2[i];
}
}
This feature is called "template argument deduction". See the link for more details.
Short version: If, in a call to a templated function, the template arguments (types, or in your case, array size) can be deduced from the arguments the function is called with (in your case, the actual array), you don't have to specify them explicitly.
This question already has answers here:
pass reference to array in C++
(3 answers)
Closed 8 years ago.
I want to pass value of array in function by reference
My first try with variable (it works well):
#include <iostream>
using namespace std;
int input(int &);
int main()
{
int a;
input(a);
cout << "the value : " << a << endl;
system("pause");
return 0;
}
int input(int &a)
{
cin >> a;
}
But when i change a to a[] like in the following code, it
doesn't work
#include <iostream.h>
using namespace std;
int input(int &[]);
int main()
{
int a[2], i;
input(a);
for(i=0;i<=2;i++)
{
cout << a << endl;
}
system("pause");
return 0;
}
int input(int &a[])
{
int i;
for(i=0;i<=2;i++)
{
cin >> a[i];
}
}
It should be:
void input(int (&a)[2]);
or simply
void input(int (&)[2]);
But in function definition, you need also to give the array name:
void input(int (&a)[2]) {...}
You need to use (&array) to clarify to the compiler that you want a reference to an array, rather than the (invalid) array of references int &array[2];.
And call it like this:
input(a);
This record
int &[]
denotes an array of references that is forbided in C++.
Declare the function the following way
void input( int ( & )[2] );
Also you are using invalid range of indeces. The valid range is [0, 1]. So the function will look as
void input( int ( &a )[2] );
{
for ( size_t i = 0; i < 2; i++ ) std::cin >> a[i];
}
Also you could define the function the following way
void input( int a[], size_t n );
{
for ( size_t i = 0; i < n; i++ ) std::cin >> a[i];
}
and call it as
input( a, 2 );
The syntax for returning and taking array references is:
template<typename T, size_t N>
T(&do_nothing(T(&arg)[N]))[N]
{
return arg;
}
Or, more simply with a templated type alias:
template<typename T, size_t N> using arrayref = T(&)[N];
template<typename T, size_t N>
arrayref<T, N> do_nothing(arrayref<T, N> arg)
{
return arg;
}
When you have defined the previous type alias template, it becomes very simple to work with array references, e.g. This is how you would declare a function that takes a reference to an array of two integers:
void give_me_two_ints(arrayref<int, 2> two_ints);
To be used like:
int a[] = {1,2,3};
for(auto const& i : do_nothing(a)) std::cout << i << "\n";
I want to pass multiple compare functions to the selection sort function as shown below but i get the fallowing error :
Error 1 error C2664: 'sort' : cannot convert parameter 3 from 'bool (__cdecl *)(int,int)' to 'bool *(__cdecl *)(T,T)' c:\users\milad\documents\visual studio 2008\projects\functionpass\functionpass\passcompare.cpp 49 FunctionPass
Code :
bool integerCompare (int a , int b)
{
return(a<b);
}
bool charCompare (char a , char b)
{
return(a<b);
}
bool stringCompare (string a , string b)
{
if(a.compare(b)<0) return true;
else return false;
}
template <class T>
void sort(T x[], int n , bool(*whichCompare(T,T))) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if ((*whichCompare)(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
int temp = x[pass];
x[pass] = x[potentialSmallest];
x[potentialSmallest] = temp;
}
}
template <typename T>
void printArray(T a[], int size)
{
for(int i=0;i<size;i++)
cout<<" "<<a[i];
}
int main()
{
int intArray[] = {1,7,-8,-14,46,33,4};
sort <int>(intArray , 7 , integerCompare);
printArray<int>(intArray,7);
}
You have this:
template <class T> void sort(T x[], int n , bool(*whichCompare(T,T)))
{ /*...*/ }
The parameter declaration for a pointer to a function returning a bool and two arguments of type T is wrong. You probably really wanted:
template <class T> void sort(T x[], int n , bool (*whichCompare)(T,T))
{ /*...*/ }
Although typically functions like these are written like this:
template <class T, typename Functor>
void sort(T x[], int n , Functor whichCompare)
{
// ...
bool result = whichCompare(x[i], x[potentialSmallest]);
// ...
}
This way, users can not only pass in function pointers, but function objects that provides an operator()():
struct MyIntegerCompareFunctor
{
bool operator()(int a, int b) { return a < b; }
};
sort(intArray, 7, MyIntegerCompareFunctor());
sort(intArray, 7, &integerCompare); // Works too
Some of the algorithms provided by the C++ standard libraries are written like this.
See my corrections in the lines that have whichCompare in them.
template <class T>
void sort(T x[], int n , bool(*whichCompare)(T,T)) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if (whichCompare(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
int temp = x[pass];
x[pass] = x[potentialSmallest];
x[potentialSmallest] = temp;
}
}
You could also templatise the function itself thus:
template< typename T, typename Pred >
void sort( T x[], int n, Pred whichCompare )
{ // etc.
}
I used to do this initially just because it was easier but also allows functors / boost-function/boost-bind etc. to be used with your algorithm.
there is a much more sexy solution:
bool integerCompare (int a , int b)
{
return(a<b);
}
bool charCompare (char a , char b)
{
return(a<b);
}
bool stringCompare (string a , string b)
{
return (a.compare(b)<0);
}
template <typename T, size_t n >
void sort(T (&x)[n], bool whichCompare (T,T) ) // n=size of the array
{
for (int pass=0; pass<n-1; pass++) {
int potentialSmallest = pass;
for (int i=pass+1; i<n; i++) {
if (whichCompare(x[i],x[potentialSmallest])) {
potentialSmallest = i;
}
}
std::swap(x[pass], x[potentialSmallest]);
}
}
template <typename T, size_t n>
void printArray(T (&a)[n])
{
for(int i=0;i<n;i++)
cout<<" "<<a[i];
}
int main()
{
int intArray[] = {1,7,-8,-14,46,33,4};
sort (intArray, integerCompare);
printArray(intArray);
}