交换属性a [i] == i [a]

时间:2010-08-31 19:38:07

标签: c++

对于内置类型的整数数组,请说

int a[10];
int i = 2;
a[i] = 10;

替代地

i[a] = 10;

因为

a[i]是一个后缀表达式,*(a+i)*(i+a),因为可以添加的换向属性。

我想为用户定义的类型说明

class Dummy
{
//
};

有可能吗? 如果是,那怎么样? 如果不是那么为什么?

编辑: - 我知道它很丑,但是代码编译后: - 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;
}

6 个答案:

答案 0 :(得分:15)

这是不可能的,因为“operator[]应该是一个只有一个参数的非静态成员函数”(标准§13.5.5/ 1),所以你不能定义它,使得第一个参数是本地标量类型。

(此外,非静态运算符重载调用被解释为成员调用,因此第一个操作数不能被隐式转换,这与自由函数重载不同。这就是为什么在可能的情况下首选自由函数重载的一个原因。)

无论好坏,index[ object ]都是确保不会调用operator[]重载的方法。


然而。

“表达式E1[E2]*((E1)+(E2))相同(按照定义)”(第5.2.1节),operator+ 只要一个 方不是本机类型。这留下了两个选项漏洞:“数组”必须是一个类,或者“索引”必须是一个类或enum

然后,您必须定义代理类型以保存“添加”的结果,该结果定义了operator*重载。但是,海湾合作委员会不支持这一点。我会更深入地了解其他平台和参考资料。

编辑:啊,§13.6/ 13覆盖5.2.1并声明,为了解释涉及类或枚举类型的表达式,有函数T& operator[](std::ptrdiff_t, T*);T& operator[](T*, std::ptrdiff_t);。就是这样。

答案 1 :(得分:3)

使用C ++,没有什么是不可能的。然而,这是一个可怕的可怕想法。不要这样做。

#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;
}

不,真的,不要这样做!!!!!

答案 2 :(得分:2)

  

a [i] = 10;
  我[a] = 10;
  因为a [i]是一个后缀表达式,它是*(a + i)或*(i + a),因为加法的交换属性。

是。但是a[i] == i[a] == *(a+i) == *(i+a)是因为C中的符号a[i]是后一指针算术的syntactic sugar。关键字在这里“在C”。大型C ++试图从指针算法中分离出来。因此a[i]仅作为语法糖支持POD以向后兼容C.但是这对任何C ++对象都不起作用,因为操作[]具有明确的语义指定和它不允许类似C语法的技巧。

最后,不要这样做。诀窍是旧时代的一个模糊残余,并没有一个很好的理由被转世。

答案 3 :(得分:2)

完全不可能。 Potatoswatter correctly points out您无法定义任何运算符,例如operator[](int, T),因此无法对左侧的整数进行重载。

但请考虑这是有效的:

struct foo
{
    operator const foo*() const
    {
        return this;
    }
};

int main()
{
    foo f;
    5[f]; // UB
}

有没有办法利用这个?号:

  

5.2.1订阅
  后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式应具有“指向T的指针”类型,另一个表达式应具有枚举或整数类型。结果是类型为“T”的左值。类型“T”应该是完全定义的对象类型.56)表达式E1[E2]*((E1)+(E2))相同(根据定义)。

E1是整数类型,E2 必须是指针类型。所以我们不能在那里注入用户行为。

唯一剩下的就是+*。我们不能为整数类型和指针更改operator+,因为它是由语言定义的。 E1 + E2的结果将成为指针,我们也无法为指针定义operator*

因此,注入用户定义的行为是不可能的。

答案 4 :(得分:0)

您需要定义Dummy::operator[](const Dummy& ref)以展示所需的属性。例如:

#include <iostream>

class dummy
{
public:
    int operator[](const dummy& ref) { return 0; }
};

int main(int argc, char *argv[])
{
    dummy d1, d2;

    std::cout << (d1[d2] == d2[d1] ? "Yes" : "No");
}

当然这可能不是你想要的,但是棘手的一点是用你必须定义的东西替换return 0;和可能的返回类型,并且满足你的意图。 / p>

为什么你想要这个?这只是一种心理锻炼吗?

答案 5 :(得分:0)

如果Dummy可以隐式地转换为整数,那么声明并用作数组的任何Dummy都将以相同的方式工作。