Buscar..


Sintaxis

  • [[detalles]]: atributo simple sin argumentos

  • [[detalles (argumentos)]]: Atributo con argumentos

  • __attribute (detalles): No estándar GCC / Clang / IBM específico

  • __declspec (detalles): no estándar MSVC específico

[[sin retorno]]

C ++ 11

C ++ 11 introdujo el atributo [[noreturn]] . Se puede usar para que una función indique que la función no regresa a la persona que llama, ya sea ejecutando una declaración de retorno , o llegando al final si es cuerpo (es importante tener en cuenta que esto no se aplica a las funciones void , ya que devuelva a la persona que llama, simplemente no devuelven ningún valor). Dicha función puede terminar llamando a std::terminate o std::exit , o lanzando una excepción. También vale la pena señalar que una función de este tipo puede regresar ejecutando longjmp .

Por ejemplo, la función a continuación siempre lanzará una excepción o llamará std::terminate , por lo que es un buen candidato para [[noreturn]] :

[[noreturn]] void ownAssertFailureHandler(std::string message) {
    std::cerr << message << std::endl;
    if (THROW_EXCEPTION_ON_ASSERT)
        throw AssertException(std::move(message));
    std::terminate();
}

Este tipo de funcionalidad permite al compilador finalizar una función sin una declaración de retorno si sabe que el código nunca se ejecutará. Aquí, debido a que la llamada a ownAssertFailureHandler (definida anteriormente) en el código a continuación nunca regresará, el compilador no necesita agregar código debajo de esa llamada:

std::vector<int> createSequence(int end) {
    if (end > 0) {
        std::vector<int> sequence;
        sequence.reserve(end+1);
        for (int i = 0; i <= end; ++i)
            sequence.push_back(i);
        return sequence;
    }
    ownAssertFailureHandler("Negative number passed to createSequence()"s);
    // return std::vector<int>{}; //< Not needed because of [[noreturn]]
}

Es un comportamiento indefinido si la función realmente regresará, por lo que no se permite lo siguiente:

[[noreturn]] void assertPositive(int number) {
    if (number >= 0)
        return;
    else
        ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}

Tenga en cuenta que [[noreturn]] se utiliza principalmente en las funciones void. Sin embargo, esto no es un requisito, permitiendo que las funciones se usen en la programación genérica:

template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
    if (i == 0)
         i = InconsistencyHandler::correct(i);
    return 42. / i;
}

struct InconsistencyThrower {
    static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown inconsistency"s); }
}

struct InconsistencyChangeToOne {
    static int correct(int i) { return 1; }
}

double fortyTwo = fortyTwoDivideBy<InconsistencyChangeToOne>(0);
double unreachable = fortyTwoDivideBy<InconsistencyThrower>(0);

Las siguientes funciones de biblioteca estándar tienen este atributo:

  • std :: abortar
  • std :: exit
  • std :: quick_exit
  • std :: inesperado
  • std :: terminar
  • std :: rethrow_exception
  • std :: throw_with_nested
  • std :: nested_exception :: rethrow_nested

[[caer a través]]

C ++ 17

Cada vez que se termina un case en un switch , se ejecutará el código del siguiente caso. Este último se puede prevenir usando la declaración 'break'. Dado que este llamado comportamiento fallido puede introducir errores cuando no está previsto, varios compiladores y analizadores estáticos emiten una advertencia al respecto.

A partir de C ++ 17, se introdujo un atributo estándar para indicar que la advertencia no es necesaria cuando el código debe cumplirse. Los compiladores pueden dar advertencias de forma segura cuando un caso finaliza sin break o [[fallthrough]] y tiene al menos una declaración.

switch(input) {
    case 2011:
    case 2014:
    case 2017:
        std::cout << "Using modern C++" << std::endl;
        [[fallthrough]]; // > No warning
    case 1998:
    case 2003:
        standard = input;
}

Consulte la propuesta para obtener ejemplos más detallados sobre cómo se puede usar [[fallthrough]] .

[[obsoleto]] y [[obsoleto ("motivo")]]

C ++ 14

C ++ 14 introdujo una forma estándar de desaprobar funciones a través de atributos. [[deprecated]] se puede usar para indicar que una función está en desuso. [[deprecated("reason")]] permite agregar una razón específica que puede ser mostrada por el compilador.

void function(std::unique_ptr<A> &&a);

// Provides specific message which helps other programmers fixing there code
[[deprecated("Use the variant with unique_ptr instead, this function will be removed in the next release")]]
void function(std::auto_ptr<A> a);

// No message, will result in generic warning if called.
[[deprecated]]
void function(A *a);

Este atributo puede ser aplicado a:

  • la declaracion de una clase
  • un nombre de typedef
  • una variable
  • un miembro de datos no estáticos
  • Una función
  • una enumeración
  • una plantilla de especialización

(ref. c ++ 14 borrador estándar : 7.6.5 Atributo obsoleto)

[[nodiscard]]

C ++ 17

El atributo [[nodiscard]] se puede usar para indicar que el valor de retorno de una función no debe ignorarse cuando se realiza una llamada de función. Si se ignora el valor de retorno, el compilador debe dar una advertencia sobre esto. El atributo se puede agregar a:

  • Definición de una función
  • Un tipo

Agregar el atributo a un tipo tiene el mismo comportamiento que agregar el atributo a cada función que devuelve este tipo.

template<typename Function>
[[nodiscard]] Finally<std::decay_t<Function>> onExit(Function &&f);

void f(int &i) {
    assert(i == 0);                    // Just to make comments clear!
    ++i;                               // i == 1
    auto exit1 = onExit([&i]{ --i; }); // Reduce by 1 on exiting f()
    ++i;                               // i == 2
    onExit([&i]{ --i; });              // BUG: Reducing by 1 directly
                                       //      Compiler warning expected
    std::cout << i << std::end;        // Expected: 2, Real: 1
}

Consulte la propuesta para obtener ejemplos más detallados sobre cómo se puede usar [[nodiscard]] .

Nota: Los detalles de la implementación de Finally / onExit se omiten en el ejemplo, vea Finally / ScopeExit .

[[maybe_unused]]

El atributo [[maybe_unused]] se crea para indicar en el código que cierta lógica podría no ser utilizada. Esto se vincula a menudo con las condiciones del preprocesador, donde se puede usar o no. Como los compiladores pueden dar advertencias sobre variables no utilizadas, esta es una forma de suprimirlas indicando la intención.

Un ejemplo típico de las variables que se necesitan en las construcciones de depuración cuando no se necesitan en producción son los valores de retorno que indican el éxito. En las compilaciones de depuración, la condición debe ser confirmada, aunque en producción, estas afirmaciones se han eliminado.

[[maybe_unused]] auto mapInsertResult = configuration.emplace("LicenseInfo", stringifiedLicenseInfo);
assert(mapInsertResult.second); // We only get called during startup, so we can't be in the map

Un ejemplo más complejo son diferentes tipos de funciones de ayuda que se encuentran en un espacio de nombres sin nombre. Si estas funciones no se utilizan durante la compilación, un compilador puede dar una advertencia sobre ellas. Idealmente, le gustaría protegerlos con las mismas etiquetas de preprocesador que la persona que llama, aunque como esto podría volverse complejo, el atributo [[maybe_unused]] es una alternativa más [[maybe_unused]] mantener.

namespace {
    [[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath);
    // TODO: Reuse this on BSD, MAC ...
    [[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath);
}

std::string createConfigFilePath(const std::string &relativePath) {
#if OS == "WINDOWS"
      return createWindowsConfigFilePath(relativePath);
#elif OS == "LINUX"
      return createLinuxConfigFilePath(relativePath);
#else
#error "OS is not yet supported"
#endif
}

Consulte la propuesta para obtener ejemplos más detallados sobre cómo se puede usar [[maybe_unused]] .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow