For a built in type integer array say
int a[10];
int i = 2;
a[i] = 10;
alternatively
i[a] = 10;
because
a[i]
is a postfix expression that is *(a+i)
or *(i+a)
because commutative property of addition.
I want to achieve that for a userdefined type say
class Dummy
{
//
};
Is it possible? If yes then how? If no then why?
EDIT :- I know it is ugly but following code compiles :- g++ -dumpversion 4.3.3
#include <stdio.h>
#include<iostream>
#include <string.h>
#include <malloc.h>
using namespace std;
int main()
{
string ArrayS[10];
2[ArrayS] = "ADASD" ;
cout << 2[ArrayS] << endl;
return 0;
}
It is impossible because "operator[]
shall be a non-static member function with exactly one parameter" (standard §13.5.5/1), so you cannot define it such that the first argument is of native scalar type.
(Furthermore, a nonstatic operator overload call is interpreted as a member call, so the first operand cannot be implicitly converted, unlike a free function overload. This is one reason why free function overloads are preferred when possible.)
For better or worse, index[ object ]
is a way to ensure that no operator[]
overload gets called.
"The expression E1[E2]
is identical (by definition) to *((E1)+(E2))
" (§5.2.1) and operator+
can be overloaded so long as one side is not native type. This leaves two options vulnerabilities: the "array" must be a class, or the "index" must be a class or enum
.
You would then have to define a proxy type to hold the result of "addition," which defines an operator*
overload. GCC does not support this, however. I'll look deeper into other platforms and references.
Edit: Ah, §13.6/13 overrides 5.2.1 and declares that, for the sake of interpreting an expression involving class or enumeration type, there are functions T& operator[](std::ptrdiff_t, T*);
and T& operator[](T*, std::ptrdiff_t);
. So that's that.
With C++, nothing is impossible. It is however, a terrible terrible idea. Don't do this.
#include <memory>
#include <stdlib.h>
#include <stdio.h>
void *aligned_malloc( size_t bytes, size_t alignment ) {
void *p = malloc( bytes + alignment ), *pa = reinterpret_cast<void*>( reinterpret_cast<size_t>(p) + alignment &- alignment );
reinterpret_cast<void**>(pa)[-1] = p;
return pa;
}
void aligned_free( void *pa ) {
void *p = reinterpret_cast<void**>(pa)[-1];
free( p );
}
struct SupportReverseIndexer
{
class IndexerReversal
{
static const size_t alignment;
friend struct SupportReverseIndexer;
friend class std::auto_ptr<IndexerReversal>;
struct SupportReverseIndexer* const m_parent;
IndexerReversal(struct SupportReverseIndexer* parent) : m_parent(parent) {}
void* operator new(size_t bytes) { return aligned_malloc(bytes, alignment); }
void operator delete(void* p) { aligned_free(p); }
static struct SupportReverseIndexer* getParent(IndexerReversal* pThis)
{
size_t iThis = reinterpret_cast<size_t>(pThis);
iThis += alignment >> 1;
iThis &= ~(alignment - 1);
return reinterpret_cast<IndexerReversal*>(iThis)->m_parent;
}
public:
operator size_t() { struct SupportReverseIndexer* const parent = getParent(this); return parent->indexer(this-parent->ir.get()); }
};
SupportReverseIndexer() : ir(new IndexerReversal(this)) {}
operator IndexerReversal*() { return ir.get(); }
private:
std::auto_ptr<IndexerReversal> ir;
size_t indexer(size_t index) { printf("Custom operator[] called, index = %i\n", index); return index; }
};
const size_t SupportReverseIndexer::IndexerReversal::alignment = 0x10000 * sizeof(SupportReverseIndexer::IndexerReversal);
int main(void)
{
SupportReverseIndexer sri;
int a = sri[2];
a = 3[sri];
a = (-5)[sri];
return 0;
}
No, really, DON'T DO THIS!!!!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With