2016-03-28 21 views
5

W Pythonie mamy ładną, prostą składnię, która przenosi arbitralne int/float na potęgę. Mianowicie, bo nie-programistów Pythona, możemy mieć następujące oświadczenie:Przeciążanie ** w C++

y = 2 ** 3 
print y 

Drukuje 8 do konsoli i ma ładny składnię jak jest zbudowany w operatora „Power”. Czy możliwe jest przeciążenie "**" jako pojedynczego operatora w C++? W szczególności, chcę osiągnąć coś takiego:

int a = 2; 
int b = 3; 
cout << (a**b) << endl; 

lub, jeżeli nie jest to możliwe, coś takiego:

MyInt a = new MyInt(2); // Wrapper class around ints to play nicely with ** 
MyInt b = new MyInt(3); 
cout << (a**b) << end; // Assume ostream overridden for MyInt 

Powinny one również wydrukować 8 do konsoli. Rozumiem, że znacznie łatwiej byłoby zastąpić operatora "^", aby zrobić to samo, ale najbardziej interesuje mnie, czy mogę przeciążyć "**". Czy operator "*" (dla przypadku klasy MyInt, gdyby była funkcją członka) musi sprawdzić, czy argument jest inny "*", ponieważ nie znam sposobu na określenie "**" jako jeden operator? Czy możliwe jest przekazanie operatora jako argumentu?

Dodatkowe/premiowe zastrzeżenie, o ile jest to możliwe (tak jakbym jeszcze nie powiedział): Brak makr !!!

+2

Nazywa przeciążanie operatorów, ponieważ przeciążasz operatorów. ** nie jest operatorem. – DeiDei

+1

Nie przeciążaj operatora^w znaczeniu mocy, ma on niższy priorytet niż ==, + lub - więc spowoduje wiele niespodzianek. –

+0

@ ÖöTiib Świetny punkt! – mwm314

Odpowiedz

4

Masz na myśli coś takiego?

#include <iostream> 
#include <cmath> 

struct MyInt { 
    int val; 
    struct MyProxy { int val; }; 

    MyProxy operator *() const{ return MyProxy{val}; } 
    MyInt operator * (const MyProxy& b) { return MyInt{ static_cast<int>(std::pow(val, b.val)) }; } 

}; 

std::ostream& operator << (std::ostream& o, const MyInt& m) { return o << m.val; } 

int main(){ 
    MyInt a{5}, b{3}; 
    std::cout << a**b << std::endl; 
} 

Zobacz żyć tutaj http://coliru.stacked-crooked.com/a/ab56b9cd6e422e12

Objaśnienie:

  1. przeciążać jednoskładnikowa * operator wrócić obiekt proxy
  2. przeciążać binarny * operatora do korzystania z serwera proxy ... Proste :-)
  3. Użyłem klasy proxy, aby uniknąć subtelnych błędów ..

C++ jest zabawa ... Chcę wierzyć robisz to dla zabawy i nie w produkcji ... spowodować jego bardzo zły pomysł w produkcji, po prostu zadzwoń std::pow

+1

Tylko dlatego, że coś jest możliwe, to nie znaczy, że to dobry pomysł ... –

+2

Tak ... Wiem :-) ... Chcę wierzyć, że OP chce to zrobić dla zabawy, a nie w kodzie produkcyjnym – WhiZTiM

+0

Dla jasności i jednoznaczności: może to być zabawna gra (i otwarcie przyznam, zrobiłem to sam, i mi się to podobało), ale ** nie rób tego w kodzie produkcyjnym lub cokolwiek innego poza czystym kodem wyrzucanym, napisanym tylko po to, aby cieszyć się grą. –

4

Krótka odpowiedź: Nie. Nie ma możliwości "przeciążenia" dowolnych sekwencji znaku/tokena w C++.

Dłuższa odpowiedź:a**b jest równoważna a * (*b), więc mógł przeciążenie zarówno binarne * (czyli mnożenie) i jednoskładnikowa * (tj dereference) w jakiś sposób brutto. Ale byłoby to całkowicie nieprzejrzyste/nieoczekiwane dla każdego, kto czyta twój kod i bolesne do debugowania/utrzymywania w przyszłości.

Wystarczy napisać funkcję o nazwie pow()!

+0

To bardzo brudna sztuczka. – mwm314

+0

Uważam, że nie można przekazać operatora jako argumentu? – mwm314