c++ - switch - ¿Puedo escribir esta declaración if con una declaración de variable en una línea?
switch c++ (5)
Antes de C ++ 17 puedes definir una clase contenedora, como aquí:
#include <utility>
template<typename T>
class NotT
{
T t;
public:
template<typename U>
NotT(U&& u) : t(std::move(u)) {}
explicit operator bool() const { return !t; }
T & value() { return t; }
T const& value() const { return t; }
};
template<typename T> NotT<T> Not(T&& t)
{
return NotT<T>(std::move(t));
}
#include <memory>
#include <iostream>
int main()
{
if(auto p=Not(std::make_shared<int>(2134)))
std::cout << "!p: p=" << p.value().get() << ''/n'';
else
std::cout << "!!p: p=" << p.value().get() << ", *p=" << *p.value() << ''/n'';
}
Me preguntaba si había una manera de poner esto en una línea.
if (auto r = getGlobalObjectByName(word)) r->doSomething; // This works fine
if (!auto r = getGlobalObjectByName(word)) r->doSomething; // Says "expected an expression"
if (auto r = getGlobalObjectByName(word) == false) r->doSomething; // Also doesn''t work.
También traté de rodearlo con corchetes adicionales, pero parece que no funciona. Encuentro esto realmente conveniente hacerlo en una línea.
Desde C ++ 17 puedes usar un inicializador if-statement :
if (auto r = getGlobalObjectByName(word); !r) r->doSomething;
La semántica es:
if (init-statement; condition) statement
La única diferencia con respecto a la instrucción if "tradicional" es la instrucción init-statement
, que inicializa una variable en el ámbito del bloque, similar a for-loops.
Lo que estás tratando de hacer está bien. Al definir la variable dentro de si restringe su alcance . Eso ayuda a reducir el número de variables perdidas después de que hayan cumplido su propósito.
Usando esta técnica, si quieres seguir el camino negativo , necesitas usar algo como esto:
if(auto r = getGlobalObjectByName(word))
{
r->doSomething();
}
else
{
// r == nullptr
// so do something else
}
Si tiene C ++ 17, use el formulario if (init statement; condition)
. Si no, tienes tres opciones:
Deja de tratar de mantener todo esto en una línea. Por ejemplo:
auto r = getGlobalObjectByName(word); if (!r) r->doSomething();
Use un
else
:if (auto r = getGlobalObjectByName(word)) {} else r->doSomething();
(Tenga en cuenta que esto requiere que r
sea un puntero inteligente con una semántica muy extraña para la función operator bool()
del operator bool()
. OTOH, supongo que esto es una pequeña pieza de código de ejemplo, en lugar de su código real).
Creo que solo usaría el formulario else
si fuera realmente importante mantener todo en una línea (para preservar un formato tabular del código, por ejemplo).
También hay una manera de hacer esto con lambdas y C ++ 14 pero parece bastante tonto.
[](auto r){ if(!r)r->doSomething(); }(getGlobalObjectByName(word));
En C ++ 11 también podrías hacer este lío horrible (la misma idea, simplemente no hay auto
)
[](decltype(getGlobalObjectByName(word)) r){ if(!r)r->doSomething(); }(getGlobalObjectByName(word));
Ciertamente, no es mejor que esta versión más clara de C ++ 11 mencionada por Martin Bonner :
{
auto r = getGlobalObjectByName(word);
if(!r)r->doSomething();
}
Aquí su código es claro que usted quiere que r
esté solo por la duración de la instrucción if.