Espacios de nombres
Variantes
Acciones

Otros operadores

De cppreference.com
< cpp‎ | language
Nombre operador Sintaxis Sobrecargable Ejemplos de prototipos (para class T)
Dentro de definición de clase Fuera de definición de clase
llamada a función a(a1, a2) Si R T::operator()(Arg1 &a1, Arg2 &a2, ... ); N/A
coma a, b Si T2& T::operator,(T2 &b); T2& operator,(const T &a, T2 &b);
operador condicional a ? b : c No N/A N/A

Contenido

[editar] Explicación

El operador llamada a función provee semántica de función para cualquier objeto.


El operador condicional (coloquialmente conocido como condicional ternario) comprueba el valor lógico de la primera expresión y, dependiendo del valor resultante, evalúa y devuelve la segunda o tercera expresión.

[editar] Operador de llamada a función integrado

Las expresiones de llamada a función tienen la forma

E ( A1, A2, A3,... )

donde

  • E es una expresión que nombra a la función
  • A1, A2, A3,... es una lista de expresiones arbitrarias que puede estar vacía, excepto el operador coma no está permitido en el nivel superior para evitar la ambigüedad.


La expresión que da nombre a la función puede ser

a) una expresión lvalue que refiere a la función
b) puntero a función
c) expresión de acceso a miembro de clase explícita que selecciona una función miembro.
d) expresión de acceso a miembro de clase implícito, por ejemplo, nombre de función miembro usada en otra función miembro.

El nombre de función (o miembro) especificado por E se puede sobrecargar, las reglas de resolución de sobrecarga se usan para decidir cual de ellas se llama.

Si E especifica una función miembro, podría ser virtual, en cuyo caso se llamará a la sobreescritura final de esa función, usando el manejador dinámico en tiempo de ejecución.

Para llamar a la función,

La expresión E así como todas la expresiones A1, A2, A3, etc, provistas como argumentos se evalúan en orden arbitrario, sin secuencia de unas respecto de las otras.

(hasta C++17)

La expresión E se secuencia antes de las expresiones A1, A2, A3 y de los argumentos por defecto, si hay. Las expresiones de arguemntos se evalúan en orden arbitrario, en secuencia indeterminada de unos respecto a los otros.

(desde C++17)

Cada parámetro de la función se inicializa con su argumento correspondiente después de la conversión implícita si es necesaria. Si no está el argumento correspondiente, se usa el argumento por defecto que corresponde, y si no hay, el programa está mal formado. Si se realiza la llamada a una función miembro, entonces el puntero this al objeto actual se convierte como si fuera conversión explícita al puntero que espera la función. La inicialización y destrucción de cada parámetro ocurre en el contexto del llamador, lo que significa que, por ejemplo, que si el constructor de un parámetro lanza una excepción, el capturador de excepción definido dentro de la función, incluso para un bloque función-try, no se considera. Si la función es una función variable (número variable de argumentos), se aplica las promociones de argumentos por defecto a todos los argumentos coincidentes con el parámetro de puntos suspensivos. La implementación define si el tiempo de vida de un parámetro finaliza cuando la función en el que se define retorna o al final de la expresión completa que lo contiene.

El tipo devuelto por una expresión de llamada a función es el tipo de retorno de la función seleccionada, seleccionado mediante enlace estático (ignorando la palabra reservada virtual), incluso si la función sobrecargada que en realidad se llama devuelve un tipo diferente. Esto permite a las funciones sobrecargadas devolver punteros o referencias a clases que son derivadas del tipo devuelto por la función base, por ejemplo, C++ soporta tipos de retorno covariantes. Si E especifica un destructor, el tipo devuelto es void.

Cuando un objeto de tipo clase X se pasa o es devuelta por una función, si cada constructor copia, constructor de movimiento, y destructor de X es trivial o eliminado, y X tiene al menos un constructor de copia o movimiento no eliminado, se permite a las implementaciones crear un objeto temporal para contener el parámetro de función u objeto de resultado.

El objeto temporal se construye con el argumento de la función o el valor devuelto, respectivamente, y el parámetro o el objeto devuelto de la función se inicializa como si se usara el constructor trivial no eliminado para copiar el temporal (incluso si ese constructor es inaccesible o no se selecciona por resolución de sobrecarga para realizar una copia o movimiento de objeto).

Esto permite que objetos de tipo clases pequeños, como std::complex o std::span, se puedan pasar o devolver por funciones en los registros.

(desde C++17)

La categoría de valor de una expresión de llamada a función es lvalue si la función devuelve una referencia lvalue o una referencia rvalue a función, es un xvalue si la función devuelve una referencia rvalue a objeto, y es un prvalue en otro caso. Si la expresión de llamada a función es un prvalue de tipo objeto, debe tener tipo completo excepto {rev inl|since=c++17|cuando el prvalue no se materializa, así como}} cuando se usa como operando de decltype (o como el operando derecho de una expresión operador coma integrado esto es el oprando de decltype).

La expresión de llamada a función es similar en sintaxis a una inicialización de valor T(), a una expresión de conversión estilo función T(A1), y a la inicialización directa de un temporal T(A1, A2, A3, ...), donde T es el nombre del tipo.

#include <cstdio>
struct S
{
    int f1(double d) {
        return printf("%f \n", d); // llamada a función de número de argumentos variable
    }
    int f2() {
        return f1(7); // llamada a función miembro, igual que this->f1()
                      // el argumento entero se convierte a double
    }
};
void f() {
   puts("función llamada"); // llamada a función
}
int main()
{
    f(); // llamada a función
    S s;
    s.f2(); // llamada a función miembro
}

Salida:

función llamada
7.000000

[editar] Operador coma integrado

Las expresiones del operador coma tienen la forma

E1 , E2

En una expresión coma E1, E2, se evalúa la expresión E1, su resultado se descarta (aunque si es de tipo clase, no será destruido hasta el final de la expresión completa que la contiene), y sus efectos secundarios se completan antes del comienzo de la evaluación de la expresión E2 (tenga en cuenta que el operator, definido por usuario no puede garantizar la secuencia) (hasta C++17).

El tipo, el valor y la categoría de valor del resultado de la expresión coma son exactamente el tipo, el valor y la categoría de valor del segundo operando, E2. Si E2 es una expresión (desde C++17) temporal, el resultado de la expresión es esa expresión (desde C++17) temporal. Si E2 es un campo de bits, el resultado es un campo de bits.

La coma en varias listas separadas por coma, como el listado de argumentos de una función (f(a, b, c)) y listado de inicialización int a[] = {1,2,3}, no es el operador coma. Si se necesita usar el operador coma en estos contextos, tiene que estar entre paréntesis: f(a, (n++, n+b), c)

#include <iostream>
int main()
{
    int n = 1;
    int m = (++n, std::cout << "n = " << n << '\n', ++n, 2*n);
    std::cout << "m = " << (++m, m) << '\n';
}

Salida:

n = 2
m = 7


[editar] Operador condicional

Las expresiones del operador condicional tienen la forma

E1 ? E2 : E3

Se evalúa el primer operando del operador condicional y se convierte contextualmente a bool. Después de que completen la evaluación de valor y todos los efectos secundarios del primer operando, si el resultado es true, se evalúa el segundo operando. Si el resultado es false, se evalúa el tercer operando.

El tipo y categoría de valor de la expresión condicional E1 ? E2 : E3 se determina de acuerdo con las siguientes reglas:

1) Si E2 o E3 tienen tipo void, entonces una de las siguientes condiciones debe ser verdadera, o el programa está mal formado:
1.1) SiE2 o E3 (pero no los dos) es una (que puede estar entre paréntesis) expresión throw. El resultado del operador condicional tiene el tipo y la categoría de valor de la otra expresión. Si la otra expresión es un campo de bits, el resultado es un campo de bits. Dicho operador condicional se usaba comúnmente en C ++ 11 constexpr programación antes de C++14.
std::string str = 2+2==4 ? "ok" : throw std::logic_error("2+2 != 4");
1.2) E2 y E3 son de tipo void (incluyendo el caso cuando los dos son expresiones throw). El resultado es un prvalue de tipo void.
2+2==4 ? throw 123 : throw 456;
2) En otro caso, si E2 o E3 son campos de bits glvalue de la misma categoría de valor y de tipos cv1 T y cv2 T, respectivamente, se considera que son de tipo cv T para el resto de esta sección, donde cv es la unión de cv1 y cv2.
(desde C++14)
3) En otro caso, si E2 y E3 tienen tipos diferentes, al menos uno es un tipo clase (con posibilidad de ser calificado constante/volátil), o ambos son glvalues de la misma categoría de valor y tienen el mismo tipo excepto la calificación constante/volátil, entonces se intenta formar una secuencia de conversión implícita ignorando el acceso a miembro, si un operando es un campo de bits o si se elimina una función de conversión (desde C++14). de cada uno de los operandos al tipo destino determinado por el otro operando, como se describe a continuación. Un opernado (denominado X) de tipo TX se puede convertir al tipo destino de otro operando (denominado Y) de tipo TY como sigue:
3.1) SiY es un lvalue, el tipo destino es TY&, y la referencia debe enlazar directamente a un lvalue;
3.2) Si Y es un xvalue, el tipo destino es TY&&, y la referencia debe enlazar directamente;
3.3) Si Y es un prvalue, o si no se pueden formar las secuencias de conversión anteriores y al menos una de TX y TY es un tipo clase (que puede se calificado constante/volátil),
3.3.1) Si TX y TY son del mismo tipo clase (ignorando la calificación constante/volátil) y TY es al menos tan calificado constante/volátil como TX, el tipo destino es TY,
3.3.2) en otro caso, si TY es clase base de TX, el tipo destino es TY con los calificadores constante/volátil de TX
struct A {}; 
struct B : A {}; 
using T = const B; 
A a = true ? A() : T(); // Y = A(), TY = A, X = T(), TX = const B. Destino = const A
3.3.3) en otro caso, el tipo de destino es el que tendría Y después de aplicar las conversiones estándar de lvalue a rvalue, matriz a puntero, y función a puntero
3.4) Si se pueden formar ambas secuencias (E2 al tipo destino de E3 y E3 al tipo destino de E2), o solamente se puede formar uno pero es una secuencia de conversión ambigua, el programa está mal formado.
3.5) Si, exactamente, se puede formar una secuencia de conversión (tenga en cuenta que todavía puede estar mal formado, por ejemplo, debido a una violación de acceso), se aplica esta secuencia de conversión y se usa el operando convertido en lugar del original por el resto de esta descripción (empezando en (4))
3.6) Si no se puede formar una secuencia de conversión, los operandos se dejan sin cambios por el resto de esta descripción.
4) Si E2 y E3 son glvalues del mismo tipo y categoría de valor, entonces el resultado tiene el mismo tipo y categoría de valor, y es un campo de bits si al menos uno, E2 o E3 es un campo de bits.
5) En otro caso, el resultado es un prvalue. Si E2 y E3 no tienen el mismo tipo, y cualquiera de los dos tiene un tipo clase (que puede estar calificado constante/volátil), a continuación se realiza la resolución de sobrecarga utilizando los candidatos integrados para intentar convertir los operandos a tipos integrados. Si la resolución de sobrecarga falla, el programa está mal formado. En otro caso, se aplican las conversiones seleccionadas y se usan los operandos convertidos en lugar de los originales para el paso 6.
6) Se aplican las conversiones de lvalue a rvalue, matriz a puntero, y función a puntero al segundo y tercer operando. Entonces,
6.1) Si ahora E2 y E3 tienen el mismo tipo, el resultado es un prvalue de ese tipo que designa un objeto temporal (hasta C++17)cuyo objeto resultado es (desde C++17) copia inicializada desde cualquier operando que se seleccionó después de evaluar E1.
6.2) Si E2 y E3 tienen tipo aritmético o enumerado: las conversiones aritméticas usuales se aplican para llegar a un tipo común, y este tipo es el resultado.
6.3) Si E2 y E3 son punteros, o uno es un puntero y el otro la constante puntero nulo, entonces se aplican conversiones de puntero y calificación para llegar a un tipo común, y este tipo es el resultado.
6.4) Si E2 y E3 son punteros a miembro, o uno es un puntero a miembro y el otro una constante puntero nulo, entonces se aplican las conversiones de puntero a miembro y calificación para llegar a un tipo común, y este tipo es el resultado.
6.5) Si E2 y E3 son constantes puntero nulo, y al menos uno de ellos es de tipo std::nullptr_t, entonces el tipo del resultado es std::nullptr_t.
6.6) En cualquier otro caso, el programa está mal formado.

Para cada par de tipos aritméticos promocionados L y R y para cada tipo P, donde P es un puntero, puntero a miembro, o tipo enumerado con ámbito, los siguientes modelos de función participan en la resolución de sobrecarga realizada en el paso 5 de las reglas anteriores:

LR operator?:(bool, L, R );
P operator?:(bool, P, P );

Donde LR es el resultado de las conversiones aritméticas usuales realizadas sobre L y R. No se puede sobre cargar el operador “?:”, esos modelos de función solamente existen con el propósito de resolución de sobrecarga.

El tipo de retorno de un operador condicional también es accesible como la característica del tipo binario std::common_type.

#include <string>
#include <iostream>
struct Node
{
    Node* next;
    int data;
    // constructor copia de copia profunda
    Node(const Node& other)
      : next(other.next ? new Node(*other.next) : NULL)
      , data(other.data)
    {}
    Node(int d) : next(NULL), data(d) {}
    ~Node() { delete next ; }
};
int main()
{   
    // ejemplo simple de rvalue 
    int n = 1>2 ? 10 : 11;  // 1>2 es falso, por lo que n = 11
    // ejemplo simple de lvalue
    int m = 10; 
    (n == m ? n : m) = 7; // n == m es falso, entonces m = 7
    std::cout << "n = " << n << "\nm = " << m; // mostrar resultado
}

Salida:

n = 11
m = 7

[editar] Biblioteca estándar

Muchas clases en la biblioteca estándar sobrecargan el operator() para ser usado como objetos de función.

elimina el objeto o matriz
(función miembro público de std::default_delete) [editar]
devuelve la suma de dos argumentos
(función miembro público de std::plus) [editar]
devuelve la diferencia entre dos argumentos
(función miembro público de std::minus) [editar]
devuelve el producto de dos argumentos
(función miembro público de std::multiplies) [editar]
devuelve el resultado de la división del primer argumento por el segundo argumento
(función miembro público de std::divides) [editar]
devuelve el resto de la división del primer argumento por el segundo argumento
(función miembro público de std::modulus) [editar]
devuelve la negación del argumento
(función miembro público de std::negate) [editar]
Comprueba si los argumentos son iguales
(función miembro público de std::equal_to) [editar]
Comprueba si los argumentos no son iguales
(función miembro público de std::not_equal_to) [editar]
Comprueba si el primer argumento es mayor que el segundo
(función miembro público de std::greater) [editar]
comprueba si el primer argumento es menor que el segundo
(función miembro público de std::less) [editar]
Comprueba si el primer argumento es mayor o igual que el segundo
(función miembro público de std::greater_equal) [editar]
Comprueba si el primer argumento es menor o igual que la segunda
(función miembro público de std::less_equal) [editar]
devuelve el AND lógico de los dos argumentos
(función miembro público de std::logical_and) [editar]
devuelve el OR lógico de los dos argumentos
(función miembro público de std::logical_or) [editar]
devuelve el NO lógico del argumento
(función miembro público de std::logical_not) [editar]
devuelve el resultado de AND entre bits de los dos argumentos
(función miembro público de std::bit_and) [editar]
Devuelve el resultado del operador OR entre bits de dos argumentos
(función miembro público de std::bit_or) [editar]
devuelve el resultado de XOR de bits de dos argumentos
(función miembro público de std::bit_xor) [editar]
devuelve el complemento lógico del resultado de una llamada al predicado almacenado
(función miembro público de std::unary_negate) [editar]
devuelve el complemento lógico del resultado de una llamada al predicado almacenado
(función miembro público de std::binary_negate) [editar]
llama a la función almacenada
(función miembro público de std::reference_wrapper) [editar]
invoca al destino
(función miembro público de std::function) [editar]
compara lexicográficamente dos cadenas usando los códigos de carácter local
(función miembro público de std::locale) [editar]
compara dos valores de tipo value_type
(función miembro público de std::map::value_compare) [editar]
compara dos valores de tipo value_type
(función miembro público de std::multimap::value_compare) [editar]
ejecuta la función
(función miembro público de std::packaged_task) [editar]
avanza el estado del motor de generación aleatorio y devuelve el valor generado
(función miembro público de std::linear_congruential_engine) [editar]
genera el siguiente número aleatorio en la distribución
(función miembro público de std::uniform_int_distribution) [editar]


El operador coma no está sobrecargado por ninguna clase en la biblioteca estándar. La biblioteca boost usa operator, en boost.assign, boost.spirit, y otras bibliotecas. La biblioteca de acceso a base de datos SOCI también sobrecarga operator,.

[editar] Informe de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 1550 C++98 No se permitía expresiones throw entre paréntesis en ?: si el otro operando no es void se aceptan expresiones throw entre paréntesis
CWG 1560 C++98 un operando void en ?: causaba una conversión lvalue a rvlaue innecesaria en el otro operando,
resultando siempre un rvalue
 ?: con void puede ser lvalue
CWG 1932 C++14 faltaban campos de bits del mismo tipo en ?: manejado por tipos subyacentes
CWG 1895 C++14 no está claro si una función de conversión eliminada o inaccesible evita la conversión en ?:,
y no se consideraba las conversiones desde la clase base a la clase derivada prvalue
se maneja como si fuera una resolución de sobrecarga

[editar] Ver también

Precedencia de operadores

Sobrecarga de operadores

Operadores comunes
asignación incremento/decremento aritmético lógico comparación acceso a miembro otros

a = b
a = rvalue
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b

a[b]
*a
&a
a->b
a.b
a->*b
a.*b

a(...)
a, b
(type) a
? :

Operadores especiales

static_cast convierte de un tipo a otro tipo compatible
dynamic_cast convierte de clase base virtual a clase derivada
const_cast convierte de un tipo a otro compatible con diferentes calificadores constante/volátil
reinterpret_cast convierte el tipo a tipo incompatible
new asigna memoria
delete desasigna memoria
sizeof consulta el tamaño de un tipo
sizeof... consulta el tamaño de un parámetro de paquete (desde C++11)
typeid consulta la información de un tipo
noexcept comprueba si una expresión puede lanzar una excepción (desde C++11)
alignof consultas requisitos de alineación de un tipo (desde C++11)

Documentacion C de Otros operadores