(Jeśli jesteś C++ 11 pro, przejdź do pogrubioną pkt.)Usuń odniesienie w decltype (powrót T zamiast T & gdzie T i jest decltype)
Powiedzmy chcę napisać szablon metoda, która wywołuje i zwraca wynik zdanym obiektu, który typ jest parametrem szablonu:
template<ReturnType, T>
ReturnType doSomething(const T & foo) {
return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}
Więc T
musi mieć metodę ReturnType T::bar() const
w celu wykorzystania w rozmowy jak ta:
struct MyClass {
...
int bar() const;
...
};
...
MyClass object;
int x = doSomething<int, MyClass>(object);
Nie trzeba pisać MyClass
dzięki wpisać odliczenia i rozmowa staje się:
int x = doSomething<int>(object);
Ale pomijając <int>
too wyniki w błąd kompilacji, ponieważ metoda nie wymaga, aby powrócić int aby być przypisane do x
później (może na przykład powrócić char
).
w C++ 0x/11 mamy auto
i decltype
z których możemy użyć, aby wywnioskować typ zwracanej metody szablonu:
template<T>
auto doSomething(const T & foo) -> decltype(foo.bar()) {
return foo.bar(); // EDIT: Might also be an expression introducing a temp val
}
Kompilator będzie teraz dowiedzieć się, co rodzaj foo.bar()
jest i po prostu używa tego jako typu zwrotu. Dzięki naszej betonu klasy MyClass
będzie to int
i dodaje wystarczyłby:
int x = doSomething(object);
Teraz moje pytanie:
Jeśli MojaKlasa definiuje bar()
jako zwrócenie int&
, rodzaj powrotu doSomething(object)
będzie również być int&
= decltype(foo.bar())
. To jest problem, ponieważ ponieważ G ++ spełnia teraz ten warunek, jestem powracający do tymczasowego odniesienia.
Jak mogę to naprawić? Czy istnieje coś takiego jak remove_reference
, które może być używane jak remove_reference(decltype(foo.bar()))
?
myślałem o tylko deklarowania metody pomocnika, który pobiera T&
i zwraca T
a następnie określić typ zwracanej doSomething
być decltype(helper(foo.bar()))
. Ale musi być lepszy sposób, czuję to.
W czym problem? Wszystko, co robisz, przekazuje referencję. I tak, istnieje 'std :: remove_reference :: type'. –
GManNickG
@GManNickG Nie chcę ostrzeżenia w moim programie. Chcę skompilować z '-Werror-Wall". Dzięki za podpowiedź 'std :: remove_reference', wiedziałem, że widziałem to wcześniej, ale nie mogłem go znaleźć w google podczas wyszukiwania" dedukcja typu szablonu C++ 11 usunąć odniesienie ", być może moje wyszukiwanie było zbyt zlokalizowane :) – leemes
Nie, mówię, że nie powinno być żadnego ostrzeżenia. Jeśli 'foo.bar()' zwraca referencję, powinieneś być w stanie zwrócić to dobrze jako odniesienie. – GManNickG