vocales contar consonantes cadenas c++ templates c++11 type-deduction

c++ - contar - Eliminar referencia en decltype(devolver T en lugar de T & donde T & es el declotipo)



contar consonantes python (1)

Para eliminar una referencia:

#include <type_traits> static_assert(std::is_same<int, std::remove_reference<int&>::type>::value, "wat");

En tu caso:

template <typename T> auto doSomething(const T& foo) -> typename std::remove_reference<decltype(foo.bar())>::type { return foo.bar(); }

Para que quede claro, tenga en cuenta que, como está escrito, devolver una referencia está bien:

#include <type_traits> struct f { int& bar() const { static int i = 0; return i; } }; template <typename T> auto doSomething(const T& foo) -> decltype(foo.bar()) { return foo.bar(); } int main() { f x; return doSomething(x); }

La referencia devuelta simplemente puede transmitirse sin error. Su ejemplo en el comentario es donde se vuelve importante y útil:

template <typename T> auto doSomething(const T& foo) -> decltype(foo.bar()) { return foo.bar() + 1; // oops }

(Si eres un profesional de C ++ 11, salta al párrafo en negrita).

Digamos que quiero escribir un método de plantilla que llame y devuelva el resultado de un objeto pasado cuyo tipo es el parámetro de la plantilla:

template<ReturnType, T> ReturnType doSomething(const T & foo) { return foo.bar(); // EDIT: Might also be an expression introducing a temp val }

Así que T tiene que tener un método ReturnType T::bar() const para ser utilizado en una llamada como esta:

struct MyClass { ... int bar() const; ... }; ... MyClass object; int x = doSomething<int, MyClass>(object);

No tenemos que escribir MyClass gracias a la deducción de tipo y la llamada se convierte en:

int x = doSomething<int>(object);

Pero omitir <int> también da como resultado un error de compilación porque el método no requiere devolver int para ser asignado a x después (podría devolver char por ejemplo).

En C ++ 0x / 11 tenemos el auto y decltype con el que podemos usar para deducir el tipo de retorno de un método de plantilla:

template<T> auto doSomething(const T & foo) -> decltype(foo.bar()) { return foo.bar(); // EDIT: Might also be an expression introducing a temp val }

El compilador ahora descubrirá cuál es el tipo de foo.bar() y solo usa esto como el tipo de devolución. Con nuestra clase concreta MyClass esto será un int y lo siguiente sería suficiente:

int x = doSomething(object);

Ahora a mi pregunta:

Si MyClass define bar() como devolver un int& , el tipo de retorno de doSomething(object) también será un int& = decltype(foo.bar()) . Esto es un problema, ya que como G ++ ahora cumple que estoy devolviendo la referencia a temporal .

¿Cómo puedo arreglar esto? ¿Hay algo así como remove_reference que se pueda usar como remove_reference(decltype(foo.bar())) ?

Pensé simplemente en declarar un método auxiliar que toma una T& y devuelve una T y luego define el tipo de retorno de doSomething para que sea de tipo decltype(helper(foo.bar())) . Pero tiene que haber una mejor manera, lo estoy sintiendo.