É possível sobrecarregar o []
operador duas vezes? Para permitir, algo como isto: function[3][3]
(como em uma matriz bidimensional).
Se for possível, gostaria de ver algum código de exemplo.
c++
operator-overloading
Icepopo
fonte
fonte
operator()(int, int)
invés ...std::vector
com um construtor de intervalo: stackoverflow.com/a/25405865/610351using array2d = std::array<std::array<int, 3>, 3>;
Respostas:
Você pode sobrecarregar
operator[]
para retornar um objeto no qual você pode usaroperator[]
novamente para obter um resultado.Então você pode usá-lo como:
Este é apenas um exemplo simples, você gostaria de adicionar um monte de verificação de limites e outras coisas, mas você entendeu.
fonte
Proxy::operator[]
deve retornarint&
apenasint
std::vector<std::vector<int>>
para evitar vazamento de memória e comportamento estranho na cópia.multi_array
eextent_gen
são bons exemplos dessa técnica. boost.org/doc/libs/1_57_0/libs/multi_array/doc/…const ArrayOfArrays arr; arr[3][5] = 42;
vai ser capaz de passar compilação e alteraçõesarr[3][5]
, que é de alguma forma diferente do que a expectativa dos usuários quearr
éconst
.Proxy::operator[]
não retorna uma referência neste código (presumindo que seu comentário não seja uma resposta a Ryan Haining). Mais importante, ifarr
is const entãooperator[]
não pode ser usado. Você teria que definir uma versão const e, claro, faria com que ela retornasseconst Proxy
. EntãoProxy
ele próprio teria métodos const e não const. E então seu exemplo ainda não compilaria, e o programador ficaria feliz que tudo está bem e bom no universo. =)Uma expressão
x[y][z]
requer que sejax[y]
avaliada como um objetod
que suported[z]
.Isso significa que
x[y]
deve ser um objeto com umoperator[]
que avalia como um "objeto proxy" que também oferece suporte aoperator[]
.Esta é a única maneira de acorrentá-los.
Como alternativa, sobrecarregue
operator()
para receber vários argumentos, de modo que você possa invocarmyObject(x,y)
.fonte
Para uma matriz bidimensional, especificamente, você pode se safar com uma única sobrecarga de operador [] que retorna um ponteiro para o primeiro elemento de cada linha.
Em seguida, você pode usar o operador de indexação integrado para acessar cada elemento da linha.
fonte
É possível se você retornar algum tipo de classe de proxy na primeira chamada []. No entanto, há outra opção: você pode sobrecarregar o operador () que pode aceitar qualquer número de argumentos (
function(3,3)
).fonte
Uma abordagem é usar
std::pair<int,int>
:Claro, você pode
typedef
opair<int,int>
fonte
nValue = theArray[{2,3}];
Você pode usar um objeto proxy, mais ou menos assim:
fonte
Ele vai ser ótimo se você pode deixar-me saber que
function
,function[x]
efunction[x][y]
são. Mas de qualquer maneira, deixe-me considerá-lo como um objeto declarado em algum lugar como(Como você disse que é sobrecarga de operador, acho que não vai se interessar por array como
SomeClass function[16][32];
)Então,
function
é uma instância do tipoSomeClass
. Em seguida, procure a declaração deSomeClass
para o tipo deoperator[]
sobrecarga de retorno , assim comoReturnType operator[](ParamType);
Então
function[x]
terá o tipoReturnType
. Procure novamenteReturnType
aoperator[]
sobrecarga. Se houver tal método, você pode usar a expressãofunction[x][y]
.Nota, ao contrário
function(x, y)
,function[x][y]
são 2 chamadas separadas. Portanto, é difícil para o compilador ou tempo de execução garantir a atomicidade a menos que você use um bloqueio no contexto. Um exemplo semelhante é, libc diz queprintf
é atômico, enquanto chamadas sucessivas para ooperator<<
fluxo de saída sobrecarregado não são. Uma declaração comopode ter problemas em aplicativos multi-thread, mas algo como
está bem.
fonte
fonte
Encontrei minha própria solução simples para isso.
fonte
Isso permite que você pegue um lambda e produza um indexador (com
[]
suporte).Suponha que você tenha um
operator()
que suporte a passagem de ambas as coordenadas em onxe como dois argumentos. Agora, o[][]
suporte de escrita é apenas:E feito. Nenhuma classe personalizada necessária.
fonte
Se, em vez de dizer um [x] [y], você gostaria de dizer um [{x, y}], você pode fazer assim:
fonte
É possível sobrecarregar multiple [] usando um manipulador de template especializado. Só para mostrar como funciona:
E agora a definição de
SubscriptHandler<ClassType,ArgType,RetType,N>
para fazer o código anterior funcionar. Isso apenas mostra como isso pode ser feito. Esta solução é ideal nem livre de erros (não threadsafe, por exemplo).fonte
Com um
std::vector<std::vector<type*>>
, você pode construir o vetor interno usando o operador de entrada customizado que itera sobre seus dados e retorna um ponteiro para cada dado.Por exemplo:
Exemplo vivo
Esta solução tem a vantagem de fornecer a você um contêiner STL real, para que você possa usar loops for especiais, algoritmos STL e assim por diante.
No entanto, ele cria vetores de ponteiros, portanto, se você estiver usando pequenas estruturas de dados como esta, poderá copiar diretamente o conteúdo dentro do array.
fonte
Código de amostra:
fonte
vector <vector <T>> ou T ** é necessário apenas quando você tem linhas de comprimento variável e muito ineficiente em termos de uso / alocação de memória se você precisar de uma matriz retangular, considere fazer algumas contas em vez disso! veja o método at ():
fonte
Usando C ++ 11 e a Biblioteca Padrão, você pode fazer uma bela matriz bidimensional em uma única linha de código:
Ao decidir que a matriz interna representa as linhas, você acessa a matriz com uma
myMatrix[y][x]
sintaxe:E você pode usar ranged-
for
para saída:(Decidir que as
array
colunas internas representam permitiria umafoo[x][y]
sintaxe, mas você precisaria usarfor(;;)
loops mais desajeitados para exibir a saída.)fonte
Meus 5 centavos.
Eu sabia intuitivamente que precisava fazer muitos códigos clichê.
É por isso que, em vez de operator [], fiz operador sobrecarregado (int, int). Então, no resultado final, em vez de m [1] [2], fiz m (1,2)
Eu sei que é algo DIFERENTE, mas ainda é muito intuitivo e parece um script matemático.
fonte
A solução mais curta e fácil:
fonte