Sobrecarregando operador-> quando operador* retorna temporário
-
21-12-2019 - |
Pergunta
Tenho duas classes com a seguinte estrutura:
struct A {
A transform() const;
};
struct B {
// returns a temporary A
A operator*() const;
};
O *
operador pode parecer um pouco estranho aqui, mas dado o contexto de seu uso é bastante natural.Na verdade, B
realmente existe apenas para fornecer algum açúcar sintático para uma linguagem incorporada, portanto, seus métodos e operadores são projetados para dar a aparência desejada ao código.Dado B b
, obtendo o associado A
é rápido, *b
.Às vezes quero ativar a transformação A
imediatamente.Atualmente, isso requer alguns parênteses extras (*b).transform()
.Parece haver uma simplificação natural, nomeadamente b->transform()
.Mas operator ->
é suposto retornar um ponteiro e operator *
é retorna um temporário.Como posso implementar uma sobrecarga como essa?
Solução
Isenção de responsabilidade:Não sou responsável por quaisquer confusões que surjam ao alterar a categoria de valor dos operadores sobrecarregados em relação aos seus equivalentes integrados.
struct just_some_type
{
int m;
int transform() { return m; }
};
// the intermediate helper stops the recurring application of ->
// if the lhs of -> is of a class type
struct intermediate_helper
{
just_some_type member;
just_some_type* operator->() { return &member; }
};
struct ptr_like
{
just_some_type operator*()
{ return {42}; }
intermediate_helper operator->()
{ return {{42}}; }
};
Exemplo de uso:
#include <iostream>
int main()
{
auto p = ptr_like{};
std::cout << (*p).transform() << "\n";
std::cout << p->transform() << "\n";
}
Nota importante: o objeto atuado em p->
é um lvalue, como o embutido ->
é aplicado a um ponteiro!Por exemplo.se você se qualificar transform
com um lvalue-ref como int transform() &;
, então a versão (*p).transform()
não conseguirá compilar, mas p->transform()
ainda é legal.