Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commutative property a[i] == i[a]

Tags:

c++

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;
}
like image 822
Sudhendu Sharma Avatar asked Aug 31 '10 19:08

Sudhendu Sharma


2 Answers

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.


However.

"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.

like image 176
Potatoswatter Avatar answered Sep 28 '22 09:09

Potatoswatter


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!!!!!

like image 45
Ben Voigt Avatar answered Sep 28 '22 08:09

Ben Voigt