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.