Return an array from a C++ function - c++

My question is similar to this one, but not the same. That one is input array then return array. Mine is input integers, and return array.
I have an array that gets a few numbers, and makes it an array.
int makearr(int a, int b, int c){
arr[2]={a,b,c};
return?//how can I return it
}
int main(){
//and use it?
}
All I want is to make the array, and display it.
Note:
Sorry, my software doesn't support tuples.

A vector?
template <typename T>
std::vector<T> makearr (T a, T b, T c)
{
T d[] = { a, b, c };
return std::vector<T>(d, d + 3);
}
std::vector<int> x = makearr(1, 2, 3);
// access x[i]
If all manner of standard containers are verboten, then:
template <typename T> struct three { T d[3]; };
template <typename T>
three<T> makearr (T a, T b, T c)
{
three<T> d = { { a, b, c } };
return d;
}
three<int> x = makearr(1, 2, 3);
// access x.d[i]
Borrowing from here and here, I cobbled together this C++11 solution that doesn't use standard containers:
template <typename T, unsigned N>
struct argh {
argh (std::initializer_list<T> i) {
std::copy_n(i.begin(), std::min(i.size(), N), v_);
}
T & operator [] (int i) { return v_[i]; }
const T & operator [] (int i) const { return v_[i]; }
private:
T v_[N];
};
template <typename T, typename... Type>
auto makearr (T&& val, Type&&... vals) -> argh<T, 1 + sizeof...(Type)>
{
argh<T, 1 + sizeof...(Type)> arr = { val, vals... };
return arr;
}
auto x = makearr(1, 2, 3);
// access x[i]

here nothing complex is required, you just need to return an address of your first array element to a pointer,which will ultimately display the array entries. Array must be declared globally so that it is known to ptr in main().
the code is wrriten below:
int arr[3]; //Declare it globally
int main()
{
int *ptr;
ptr=makearr(2,4,5);
for(int i=0;i<3;i++)
{
cout<<*ptr<<endl;
ptr++;
}
return 0;
}
int* makearr(int a,int b,int c)
{
arr[0]=a;arr[1]=b;arr[2]=c;
return(&arr[0])
}

A pointer? You can store the integers in either an integer array or in an integer pointer. A function cannot return an array, however it can return a pointer.
int* makearr(int a, int b, int c){
int *array = new int[3];
array = &a;
array+1 = &b;
array+2 = &c;
return array;
}
int main(){
int* arr = makearr(1,2,3);
// Do something with the array. Access the elements by dereferencing the pointer variable
std::cout<<*arr<<" "<<*(arr+1);
delete arr;
return 0;
}
This code however has a potential memory leak if you do not delete the array pointer in your main(or wherever you invoke the makearr method from)

Related

Creating a Matrix class with overloaded Single and Double array index operators [duplicate]

Is it possible to overload [] operator twice? To allow, something like this: function[3][3](like in a two dimensional array).
If it is possible, I would like to see some example code.
You can overload operator[] to return an object on which you can use operator[] again to get a result.
class ArrayOfArrays {
public:
ArrayOfArrays() {
_arrayofarrays = new int*[10];
for(int i = 0; i < 10; ++i)
_arrayofarrays[i] = new int[10];
}
class Proxy {
public:
Proxy(int* _array) : _array(_array) { }
int operator[](int index) {
return _array[index];
}
private:
int* _array;
};
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
private:
int** _arrayofarrays;
};
Then you can use it like:
ArrayOfArrays aoa;
aoa[3][5];
This is just a simple example, you'd want to add a bunch of bounds checking and stuff, but you get the idea.
For a two dimensional array, specifically, you might get away with a single operator[] overload that returns a pointer to the first element of each row.
Then you can use the built-in indexing operator to access each element within the row.
An expression x[y][z] requires that x[y] evaluates to an object d that supports d[z].
This means that x[y] should be an object with an operator[] that evaluates to a "proxy object" that also supports an operator[].
This is the only way to chain them.
Alternatively, overload operator() to take multiple arguments, such that you might invoke myObject(x,y).
It is possible if you return some kind of proxy class in first [] call. However, there is other option: you can overload operator() that can accept any number of arguments (function(3,3)).
One approach is using std::pair<int,int>:
class Array2D
{
int** m_p2dArray;
public:
int operator[](const std::pair<int,int>& Index)
{
return m_p2dArray[Index.first][Index.second];
}
};
int main()
{
Array2D theArray;
pair<int, int> theIndex(2,3);
int nValue;
nValue = theArray[theIndex];
}
Of course, you may typedef the pair<int,int>
You can use a proxy object, something like this:
#include <iostream>
struct Object
{
struct Proxy
{
Object *mObj;
int mI;
Proxy(Object *obj, int i)
: mObj(obj), mI(i)
{
}
int operator[](int j)
{
return mI * j;
}
};
Proxy operator[](int i)
{
return Proxy(this, i);
}
};
int main()
{
Object o;
std::cout << o[2][3] << std::endl;
}
If, instead of saying a[x][y], you would like to say a[{x,y}], you can do like this:
struct Coordinate { int x, y; }
class Matrix {
int** data;
operator[](Coordinate c) {
return data[c.y][c.x];
}
}
It 'll be great if you can let me know what function, function[x] and function[x][y] are. But anyway let me consider it as an object declared somewhere like
SomeClass function;
(Because you said that it's operator overload, I think you won't be interested at array like SomeClass function[16][32];)
So function is an instance of type SomeClass. Then look up declaration of SomeClass for the return type of operator[] overload, just like
ReturnType operator[](ParamType);
Then function[x] will have the type ReturnType. Again look up ReturnType for the operator[] overload. If there is such a method, you could then use the expression function[x][y].
Note, unlike function(x, y), function[x][y] are 2 separate calls. So it's hard for compiler or runtime garantees the atomicity unless you use a lock in the context. A similar example is, libc says printf is atomic while successively calls to the overloaded operator<< in output stream are not. A statement like
std::cout << "hello" << std::endl;
might have problem in multi-thread application, but something like
printf("%s%s", "hello", "\n");
is fine.
template<class F>
struct indexer_t{
F f;
template<class I>
std::result_of_t<F const&(I)> operator[](I&&i)const{
return f(std::forward<I>(i))1;
}
};
template<class F>
indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
This lets you take a lambda, and produce an indexer (with [] support).
Suppose you have an operator() that supports passing both coordinates at onxe as two arguments. Now writing [][] support is just:
auto operator[](size_t i){
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
auto operator[](size_t i)const{
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
And done. No custom class required.
#include<iostream>
using namespace std;
class Array
{
private: int *p;
public:
int length;
Array(int size = 0): length(size)
{
p=new int(length);
}
int& operator [](const int k)
{
return p[k];
}
};
class Matrix
{
private: Array *p;
public:
int r,c;
Matrix(int i=0, int j=0):r(i), c(j)
{
p= new Array[r];
}
Array& operator [](const int& i)
{
return p[i];
}
};
/*Driver program*/
int main()
{
Matrix M1(3,3); /*for checking purpose*/
M1[2][2]=5;
}
struct test
{
using array_reference = int(&)[32][32];
array_reference operator [] (std::size_t index)
{
return m_data[index];
}
private:
int m_data[32][32][32];
};
Found my own simple solution to this.
vector< vector< T > > or T** is required only when you have rows of variable length
and way too inefficient in terms of memory usage/allocations
if you require rectangular array consider doing some math instead!
see at() method:
template<typename T > class array2d {
protected:
std::vector< T > _dataStore;
size_t _sx;
public:
array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {}
T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; }
const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; }
const T& get( size_t x, size_t y ) const { return at(x,y); }
void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; }
};
The shortest and easiest solution:
class Matrix
{
public:
float m_matrix[4][4];
// for statements like matrix[0][0] = 1;
float* operator [] (int index)
{
return m_matrix[index];
}
// for statements like matrix[0][0] = otherMatrix[0][0];
const float* operator [] (int index) const
{
return m_matrix[index];
}
};
It is possible to overload multiple [] using a specialized template handler. Just to show how it works :
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
// the number '3' is the number of [] to overload (fixed at compile time)
struct TestClass : public SubscriptHandler<TestClass,int,int,3> {
// the arguments will be packed in reverse order into a std::array of size 3
// and the last [] will forward them to callSubscript()
int callSubscript(array<int,3>& v) {
return accumulate(v.begin(),v.end(),0);
}
};
int main() {
TestClass a;
cout<<a[3][2][9]; // prints 14 (3+2+9)
return 0;
}
And now the definition of SubscriptHandler<ClassType,ArgType,RetType,N> to make the previous code work. It only shows how it can be done. This solution is optimal nor bug-free (not threadsafe for instance).
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler;
template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ {
ClassType*obj;
array<ArgType,N+1> *arr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.obj = obj;
s.arr = arr;
arr->at(Recursion)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> {
ClassType*obj;
array<ArgType,N+1> *arr;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
RetType operator[](const ArgType& arg){
arr->at(0) = arg;
return obj->callSubscript(*arr);
}
};
template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{
array<ArgType,N> arr;
ClassType*ptr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype;
protected:
SubscriptHandler() {
ptr=(ClassType*)this;
}
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.arr=&arr;
s.obj=ptr;
s.arr->at(N-1)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{
RetType operator[](const ArgType&arg) {
array<ArgType,1> arr;
arr.at(0)=arg;
return ((ClassType*)this)->callSubscript(arr);
}
};
With a std::vector<std::vector<type*>>, you can build the inside vector using custom input operator that iterate over your data and return a pointer to each data.
For example:
size_t w, h;
int* myData = retrieveData(&w, &h);
std::vector<std::vector<int*> > data;
data.reserve(w);
template<typename T>
struct myIterator : public std::iterator<std::input_iterator_tag, T*>
{
myIterator(T* data) :
_data(data)
{}
T* _data;
bool operator==(const myIterator& rhs){return rhs.data == data;}
bool operator!=(const myIterator& rhs){return rhs.data != data;}
T* operator*(){return data;}
T* operator->(){return data;}
myIterator& operator++(){data = &data[1]; return *this; }
};
for (size_t i = 0; i < w; ++i)
{
data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]),
myIterator<int>(&myData[(i + 1) * h])));
}
Live example
This solution has the advantage of providing you with a real STL container, so you can use special for loops, STL algorithms, and so on.
for (size_t i = 0; i < w; ++i)
for (size_t j = 0; j < h; ++j)
std::cout << *data[i][j] << std::endl;
However, it does create vectors of pointers, so if you're using small datastructures such as this one you can directly copy the content inside the array.
Sample code:
template<class T>
class Array2D
{
public:
Array2D(int a, int b)
{
num1 = (T**)new int [a*sizeof(int*)];
for(int i = 0; i < a; i++)
num1[i] = new int [b*sizeof(int)];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
num1[i][j] = i*j;
}
}
}
class Array1D
{
public:
Array1D(int* a):temp(a) {}
T& operator[](int a)
{
return temp[a];
}
T* temp;
};
T** num1;
Array1D operator[] (int a)
{
return Array1D(num1[a]);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array2D<int> arr(20, 30);
std::cout << arr[2][3];
getchar();
return 0;
}
Using C++11 and the Standard Library you can make a very nice two-dimensional array in a single line of code:
std::array<std::array<int, columnCount>, rowCount> myMatrix {0};
std::array<std::array<std::string, columnCount>, rowCount> myStringMatrix;
std::array<std::array<Widget, columnCount>, rowCount> myWidgetMatrix;
By deciding the inner matrix represents rows, you access the matrix with an myMatrix[y][x] syntax:
myMatrix[0][0] = 1;
myMatrix[0][3] = 2;
myMatrix[3][4] = 3;
std::cout << myMatrix[3][4]; // outputs 3
myStringMatrix[2][4] = "foo";
myWidgetMatrix[1][5].doTheStuff();
And you can use ranged-for for output:
for (const auto &row : myMatrix) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
(Deciding the inner array represents columns would allow for an foo[x][y] syntax but you'd need to use clumsier for(;;) loops to display output.)

Returning reference to struct

Using overloaded [] operator , we can set a value of element inside container. E.g
class Example{
public:
Example(){
arr = new int[10];
}
int operator [] ( unsigned int i) const{
return arr[i];
}
int & operator [] ( unsigned int i){
return arr[i];
}
private:
int *arr[];
}
So using
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
We can set the value of elements. Is it possible to do something like this with struct? If we didnt have array of int but vector of structs. e.g
struct Test{
int value;
int index;
Test( int a , int b){
value = a;
index = b;
}
}
class Example{
public:
Example(){
}
int operator [] ( unsigned int i) const{
return a[i].value;
}
Test & operator [] ( unsigned int i){
Test a(0, i );
one.push_back(a);
return a -> value;
}
private:
vector<Test> a;
}
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
How can i change the the value property of returned struct same way as changing/setting value using typical int container?
Yes, it is possible.
The code has an error: return a -> value; returns an int, whereas the function operator[](unsigned int i) says it will return a reference to Test. You could instead return one[one.length()-1] so that you can say example[0]->value = 1;, where example is of type Example?
The statement example[0] is a call to operator[](unsigned int i) which returns a reference to one[0], whose type is a reference to Test.
It is perfectly valid to define operator[] to return an int, and implement it the way you did above. But that's highly unintuitive; I would certainly find it very confusing because the operator [] usually returns an element of a container, not a field of an element of a container. Better to define a separate function with self-explanatory name for that, for example int& getValue(unsigned int); for the value field and int& getIndex(unsigned int) for the index field.
#include <vector>
using namespace std;
struct Test {
int value;
int index;
Test(int a, int b) {
value = a;
index = b;
}
};
class Example {
public:
Example() {}
int operator [] (unsigned int i) const {
return _a[i].value;
}
int & operator [] (unsigned int i) {
Test a(0, i);
_a.push_back(a);
return _a[i].value;
}
private:
vector<Test> _a;
};
int main() {
Example a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
return 0;
}

Matrix Multiplication with template parameters in C++

I have a self-defined Matrix class and want to overload operator * to do matrix multiplication:
template< int R, int C>
class Matrix{
int *_mat;
int _size;
public:
Matrix(){ _size = R*C; _mat = new int[_size]{0}; }
~Matrix(){ delete []_mat; }
Matrix &operator=(const Matrix & m){/*...*/}
//...
template< int D2, int D1 > using matrix_t = int[D2][D1];
template<int R2, int C2>
Matrix<R,C2> operator*(const matrix_t<R2,C2> &mat)
{
Matrix<R,C2> result;
for(int r = 0; r < R; r++)
{
for(int c = 0; c < C2; c++)
{
for( int i; i < C; i++ ){
/*do multiplication...
result._mat[r*C2+c] = ...
*/
}
}
}
return result;
}
//...
};
Then the problem comes with Matrix<R,C2> result. The result becomes a outside object of the class. So I cannot access its private member using like result._mat[r*C2+c].
What is the solution( without changing access permission) to define my function of matrix multiplication in this class?
You could specify an operator so you can externally set the values of the matrix. Note you won't be able to use operator [] - since you can only use that with one argument (ref C++ [] array operator with multiple arguments?)
int& operator() (int row, int col) {
// todo: check array bounds
return _mat[C*row+col];
}
Usage:
result(r,c) = ...
You cannot, you can just write function like set
void set(int index, int value)
{
// check index
_mat[index] = value;
}
And then in multiplication function just call result.set(...). Instead of
result._mat[r*C2+c] = ...
just
result.set(r*C2+c, ...);
This situation is since Result is object of type Matrix<R, C2>, that is not the same type as Matrix<R, C>, so you cannot access private members of type Matrix<R, C2> in member function of type Matrix<R, C>.

Variable user-defined parameter list in C++?

I'm looking for a simple way to create a user multi-parameter receiving function,
Here's some pseudo code
#include <iostream>
struct A {
int m_num;
};
void function(A* a, ...)
{
/* Pseudo-Code here */
for each parameter do
print a->m_num
end
}
int main()
{
A *a = new A();
A *b = new A();
A *c = new A();
a->m_num = 1;
b->m_num = 10;
c->m_num = 100;
function(a,b,c);
// delete everything
return 0;
}
I can't really use boost here, so if it's possible with standard C++ ( STL Allowed ), it would be great.
EDIT: The function parameters are heterogeneous
Old school plain C variadic arguments:
#include <cstdio>
#include <stdarg.h>
struct A {
A () : m_num (0) {}
A (int v) : m_num (v) {}
int m_num;
};
void function (A *a, ...)
{
va_list ap;
A *p = a;
va_start (ap, a);
while (p != NULL)
{
printf ("%d\n", p->m_num);
p = va_arg (ap, A*);
}
va_end (ap);
}
int main()
{
A a (1), b (10), c (100);
function (&a, &b, &c, NULL);
}
Another solution if arguments are of the same type (which is your case):
#include <cstdio>
struct A {
A () : m_num (0) {}
A (int v) : m_num (v) {}
int m_num;
};
void function (A *p, A *endp)
{
while (p != endp)
{
printf ("%d\n", p->m_num);
++p;
}
}
int main()
{
A a[3];
a[0].m_num = 1;
a[1].m_num = 10;
a[2].m_num = 100;
function (a, a + sizeof (a) / sizeof(a[0]));
}
Or even more C++-style, with iterators:
#include <cstdio>
#include <vector>
#include <list>
struct A {
A () : m_num (0) {}
A (int v) : m_num (v) {}
int m_num;
};
template <typename T>
void function (T p, T endp)
{
while (p != endp)
{
printf ("%d\n", p->m_num);
++p;
}
}
int main()
{
A a[3];
a[0].m_num = 1;
a[1].m_num = 10;
a[2].m_num = 100;
function (a, a + sizeof (a) / sizeof(a[0]));
std::vector<A> av (3);
av[0].m_num = 1;
av[1].m_num = 10;
av[2].m_num = 100;
function (av.begin (), av.end ());
std::list<A> al;
al.push_back (A (1));
al.push_back (A (10));
al.push_back (A (100));
function (al.begin (), al.end ());
}
The most straightforward way is to put your parameters into a std::vector. If they're non-homogeneous you can use a vector of boost::any or boost::variant.
Alternately design your interface like streams and use an insertion like operator/function that operators on one parameter at a time.
It would look something like this, alternately using a friend free-function.
struct A
{
int m_num;
};
struct printer
{
function& operator<<(A* a)
{
/* Pseudo-Code here */
print a->m_num
return *this;
}
};
int main()
{
A *a = new A();
A *b = new A();
A *c = new A();
a->m_num = 1;
b->m_num = 10;
c->m_num = 100;
printer function;
function << a << b << c;
// delete everything
return 0;
}
If every parameter going into function is an A, I'd do it with an array of A's, as in:
int main() {
A *abc[3];
for (int i=0;i<3;i++)
abc[i]=new A();
abc[0]->m_num=1;
abc[1]->m_num=10;
abc[2]->m_num=100;
function(abc,3);
}
void function(A *vals[],int count) {
for (int i=0;i<count;i++)
print vals[i]->m_num;
}
If you have a compiler recent enough to ship with std::tuple<> or std::tr1::tuple<>, you can do the following:
#include <cstddef>
#include <tuple>
#include <iostream>
struct A
{
int m_num;
};
template<typename T>
class function_impl
{
template<std::size_t N>
static void impl(T const& tup)
{
std::cout << std::get<N>(tup)->m_num << '\n';
}
template<std::size_t N>
struct recurse_helper
{
static void invoke(T const& tup)
{
function_impl<T>::template impl<N>(tup);
recurse_helper<N + 1u>::invoke(tup);
}
};
template<>
struct recurse_helper<std::tuple_size<T>::value>
{
static void invoke(T const&) { }
};
public:
static void invoke(T const& tup)
{
recurse_helper<0u>::invoke(tup);
}
};
template<typename T>
void function(T const& tup)
{
function_impl<T>::invoke(tup);
}
int main()
{
A* a = new A();
a->m_num = 1;
A* b = new A();
b->m_num = 10;
A* c = new A();
c->m_num = 100;
function(std::tie(a, b, c));
delete c;
delete b;
delete a;
}
Note that function actually takes a singular argument, a tuple<>, rather than multiple arguments. But, unlike any varargs-based solution, this is completely type-safe.
Also note that the implementation here would be much simpler if you could use Boost.Fusion...
As a supplement.
In C++0x, you could use variadic-template to implement your function recursively:
// Just to make the compiler happy.
template <typename T>
void function(T a) = delete;
// Base case
template <>
void function(A* a) {
printf("%d\n", a->m_num);
}
// Recursion
template <typename T, typename... Args>
void function(T a, Args... args) {
function(a);
function(args...);
}
But this will generate N functions if it accepts N parameters. Alternatively, you could use an initializer_list:
void function(std::initializer_list<A*> args) {
for (auto cit = args.begin(); cit != args.end(); ++ cit)
printf("%d\n", (*cit)->m_num);
}
but you need to call function as
function({a,b,c});
// ^ ^

Member pointer to array element

It's possible to define a pointer to a member and using this later on:
struct foo
{
int a;
int b[2];
};
int main()
{
foo bar;
int foo::* aptr=&foo::a;
bar.a=1;
std::cout << bar.*aptr << std::endl;
}
Now I need to have a pointer to a specific element of an array, so normally I'd write
int foo::* bptr=&(foo::b[0]);
However, the compiler just complains about an "invalid use of non-static data member 'foo::b'"
Is it possible to do this at all (or at least without unions)?
Edit: I need a pointer to a specific element of an array, so int foo::* ptr points to the second element of the array (foo::b[1]).
Yet another edit: I need to access the element in the array by bar.*ptr=2, as the pointer gets used somewhere else, so it can't be called with bar.*ptr[1]=2 or *ptr=2.
However, the compiler just complains about an "invalid use of non-static data member 'foo::b'"
This is because foo::a and foo::b have different types. More specifically, foo::b is an array of size 2 of ints. Your pointer declaration has to be compatible i.e:
int (foo::*aptr)[2]=&foo::b;
Is it possible to do this at all (or at least without unions)?
Yes, see below:
struct foo
{
int a;
int b[2];
};
int main()
{
foo bar;
int (foo::*aptr)[2]=&foo::b;
/* this is a plain int pointer */
int *bptr=&((bar.*aptr)[1]);
bar.a=1;
bar.b[0] = 2;
bar.b[1] = 11;
std::cout << (bar.*aptr)[1] << std::endl;
std::cout << *bptr << std::endl;
}
Updated post with OP's requirements.
The problem is that, accessing an item in an array is another level of indirection from accessing a plain int. If that array was a pointer instead you wouldn't expect to be able to access the int through a member pointer.
struct foo
{
int a;
int *b;
};
int main()
{
foo bar;
int foo::* aptr=&(*foo::b); // You can't do this either!
bar.a=1;
std::cout << bar.*aptr << std::endl;
}
What you can do is define member functions that return the int you want:
struct foo
{
int a;
int *b;
int c[2];
int &GetA() { return a; } // changed to return references so you can modify the values
int &Getb() { return *b; }
template <int index>
int &GetC() { return c[index]; }
};
typedef long &(Test::*IntAccessor)();
void SetValue(foo &f, IntAccessor ptr, int newValue)
{
cout << "Value before: " << f.*ptr();
f.*ptr() = newValue;
cout << "Value after: " << f.*ptr();
}
int main()
{
IntAccessor aptr=&foo::GetA;
IntAccessor bptr=&foo::GetB;
IntAccessor cptr=&foo::GetC<1>;
int local;
foo bar;
bar.a=1;
bar.b = &local;
bar.c[1] = 2;
SetValue(bar, aptr, 2);
SetValue(bar, bptr, 3);
SetValue(bar, cptr, 4);
SetValue(bar, &foo::GetC<0>, 5);
}
Then you at least have a consistent interface to allow you to change different values for foo.
2020 update, with actual solution:
The Standard does currently not specify any way to actually work with the member pointers in a way that would allow arithmetics or anything to get the pointer to the "inner" array element
OTOH, the standard library now has all the necessities to patch the appropriate member pointer class yourself, even with the array element access.
First, the member pointers are usually implemented as "just offsets", although quite scary. Let's see an example (on g++9, arch amd64):
struct S { int a; float b[10]; };
float(S::*mptr)[10] = &S::b;
*reinterpret_cast<uintptr_t *>(&mptr) //this is 4
int S::*iptr = &S::a;
*reinterpret_cast<uintptr_t *>(&iptr) //this is 0
iptr = nullptr;
*reinterpret_cast<uintptr_t *>(&iptr) //this seems to be 18446744073709551615 on my box
Instead you can make a bit of a wrapper (it's quite long but I didn't want to remove the convenience operators):
#include <type_traits>
template<class M, typename T>
class member_ptr
{
size_t off_;
public:
member_ptr() : off_(0) {}
member_ptr(size_t offset) : off_(offset) {}
/* member access */
friend const T& operator->*(const M* a, const member_ptr<M, T>& p)
{ return (*a)->*p; }
friend T& operator->*(M* a, const member_ptr<M, T>& p)
{ return (*a)->*p; }
/* operator.* cannot be overloaded, so just take the arrow again */
friend const T& operator->*(const M& a, const member_ptr<M, T>& p)
{ return *reinterpret_cast<const T*>(reinterpret_cast<const char*>(&a) + p.off_); }
friend T& operator->*(M& a, const member_ptr<M, T>& p)
{ return *reinterpret_cast<T*>(reinterpret_cast<char*>(&a) + p.off_); }
/* convert array access to array element access */
member_ptr<M, typename std::remove_extent<T>::type> operator*() const
{ return member_ptr<M, typename std::remove_extent<T>::type>(off_); }
/* the same with offset right away */
member_ptr<M, typename std::remove_extent<T>::type> operator[](size_t offset) const
{ return member_ptr<M, typename std::remove_extent<T>::type>(off_)+offset; }
/* some operators */
member_ptr& operator++()
{ off_ += sizeof(T); return *this; };
member_ptr& operator--()
{ off_ -= sizeof(T); return *this; };
member_ptr operator++(int)
{ member_ptr copy; off_ += sizeof(T); return copy; };
member_ptr operator--(int)
{ member_ptr copy; off_ -= sizeof(T); return copy; };
member_ptr& operator+=(size_t offset)
{ off_ += offset * sizeof(T); return *this; }
member_ptr& operator-=(size_t offset)
{ off_ -= offset * sizeof(T); return *this; }
member_ptr operator+(size_t offset) const
{ auto copy = *this; copy += offset; return copy; }
member_ptr operator-(size_t offset) const
{ auto copy = *this; copy -= offset; return copy; }
size_t offset() const { return off_; }
};
template<class M, typename T>
member_ptr<M, T> make_member_ptr(T M::*a)
{ return member_ptr<M, T>(reinterpret_cast<uintptr_t>(&(((M*)nullptr)->*a)));}
Now we can make the pointer to the array element directly:
auto mp = make_member_ptr(&S::b)[2];
S s;
s->*mp = 123.4;
// s.b[2] is now expectably 123.4
Finally, if you really, really like materialized references, you may get a bit haskell-lensish and make them compose:
// in class member_ptr, note transitivity of types M -> T -> TT:
template<class TT>
member_ptr<M,TT> operator+(const member_ptr<T,TT>&t)
{ return member_ptr<M,TT>(off_ + t.offset()); }
// test:
struct A { int a; };
struct B { A arr[10]; };
B x;
auto p = make_member_ptr(&B::arr)[5] + make_member_ptr(&A::a)
x->*p = 432.1;
// x.arr[5].a is now expectably 432.1
typedef int (foo::*b_member_ptr)[2];
b_member_ptr c= &foo::b;
all works.
small trick for member and function pointers usage.
try to write
char c = &foo::b; // or any other function or member pointer
and in compiller error you will see expected type, for your case int (foo::*)[2].
EDIT
I'm not sure that what you want is legal without this pointer. For add 1 offset to your pointer you should get pointer on array from your pointer on member array. But you can dereference member pointer without this.
You can't do that out of the language itself. But you can with boost. Bind a functor to some element of that array and assign it to a boost::function:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>
#include <iostream>
struct test {
int array[3];
};
int main() {
namespace lmb = boost::lambda;
// create functor that returns test::array[1]
boost::function<int&(test&)> f;
f = lmb::bind(&test::array, lmb::_1)[1];
test t = {{ 11, 22, 33 }};
std::cout << f(t) << std::endl; // 22
f(t) = 44;
std::cout << t.array[1] << std::endl; // 44
}
I'm not sure if this will work for you or not, but I wanted to do a similar thing and got around it by approaching the problem from another direction. In my class I had several objects that I wanted to be accessible via a named identifier or iterated over in a loop. Instead of creating member pointers to the objects somewhere in the array, I simply declared all of the objects individually and created a static array of member pointers to the objects.
Like so:
struct obj
{
int somestuff;
double someotherstuff;
};
class foo
{
public:
obj apples;
obj bananas;
obj oranges;
static obj foo::* fruit[3];
void bar();
};
obj foo::* foo::fruit[3] = { &foo::apples, &foo::bananas, &foo::oranges };
void foo::bar()
{
apples.somestuff = 0;
(this->*(fruit[0])).somestuff = 5;
if( apples.somestuff != 5 )
{
// fail!
}
else
{
// success!
}
}
int main()
{
foo blee;
blee.bar();
return 0;
}
It seems to work for me. I hope that helps.