Namespaces
Variants

operador de reflexión (desde C++26)

De es.cppreference.net
 
 
Lenguaje C++
Temas generales
Control de flujo
Sentencias de ejecución condicional
if
Sentencias de iteración (bucles)
for
range-for (C++11)
Sentencias de salto
Funciones
Declaración de función
Expresión de función lambda
inline especificador
Especificaciones de excepción dinámicas (hasta C++17*)
noexcept especificador (C++11)
Excepciones
Espacios de nombres
Tipos
Especificadores
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Especificadores de duración de almacenamiento
Inicialización
Expresiones
Representaciones alternativas
Literales
Booleano - Entero - Punto flotante
Carácter - Cadena - nullptr (C++11)
Definido por el usuario (C++11)
Utilidades
Atributos (C++11)
Tipos
typedef declaración
Declaración de alias de tipo (C++11)
Conversiones explícitas
Asignación de memoria
Clases
Propiedades de función específicas de clase
explicit (C++11)
static

Funciones miembro especiales
Plantillas
Varios
 
 

El operador unario ^^, llamado operador de reflexión, produce la reflexión de la construcción de lenguaje dada, de tipo std::meta::info.

Sintaxis

^^ :: (1)
^^ nombre-de-reflexión (2)
^^ tipo-id (3)
^^ expresión-id (4)
nombre-de-reflexión - un identificador, opcionalmente calificado, opcionalmente usando desambiguador de plantilla. Esta forma tiene precedencia sobre tipo-id y expresión-id
tipo-id - un tipo-id
expresión-id - una expresión-id

La secuencia más larga de tokens que sintácticamente podría formar el operando de ^^ es analizada. Si el resultado representa una plantilla, la expresión no debe ir seguida directamente por <.

static_assert(std::meta::is_type(^^int())); // ^^int() represents the type int()
                                            // not a function call to ^^int

template<bool> struct X {};
consteval bool operator<(std::meta::info, X<false>) { return false; }
consteval void g(std::meta::info r, X<false> xv) {
    r == ^^int && true; // error: ^^ applies to the type-id int&&
    r == ^^int & true; // error: ^^ applies to the type-id int&
    r == (^^int) && true; // OK
    r == ^^int &&&& true; // error: int &&&& is not a valid type-id
    ^^X < xv; // error: reflect-expression that represents a template is followed by <
    (^^X) < xv; // OK
    ^^X<true> < xv; // OK
}

Explicación

1) La expresión ^^:: representa el espacio de nombres global.
2) En ^^reflection-name, el nombre-de-reflexión es buscado, y la representación se determina de la siguiente manera:
  • Si el desambiguador de plantilla está presente, el resultado representa la plantilla de clase nombrada por el nombre-de-clase-inyectado.
  • De lo contrario, el nombre-de-clase-inyectado debe ser no ambiguo cuando se considera como un nombre de tipo (de lo contrario, la expresión es inválida). El resultado representa el tipo así nombrado.
  • De lo contrario, si la búsqueda encuentra un conjunto de sobrecarga, ese conjunto de sobrecarga debe contener solo declaraciones de una plantilla de función única. El resultado representa esa plantilla de función.
  • De lo contrario, si la búsqueda encuentra una plantilla de clase, una plantilla de variable, o una plantilla de alias, el resultado representa esa plantilla.
  • De lo contrario, si la búsqueda encuentra un parámetro de plantilla de tipo, el resultado representa el tipo del argumento correspondiente.
  • De lo contrario, si la búsqueda encuentra un nombre typedef o un alias de tipo, el resultado representa ese alias de tipo.
template<typename T>
struct S {
    static constexpr std::meta::info r = ^^T;
    using type = T;
};
static_assert(S<int>::r == ^^int); // OK
static_assert(^^S<int>::type != ^^int); // OK

typedef struct X {} Y;
typedef struct Z {} Z;
constexpr std::meta::info e = ^^Y; // OK, represents the type alias Y
constexpr std::meta::info f = ^^Z; // OK, represents the type alias Z, not the type
  • De lo contrario, si la búsqueda encuentra un tipo de clase o un tipo de enumeración, el resultado representa ese tipo.
  • De lo contrario, si la búsqueda encuentra un miembro de clase de una unión anónima, el resultado representa ese miembro.
  • De lo contrario, el nombre-de-reflexión se considera una expresión-id (véase la forma (4) a continuación).
3) La expresión ^^type-id representa una entidad determinada de la siguiente manera:
  • Si el tipo-id designa un tipo placeholder (p.ej. auto), la expresión es inválida.
  • De lo contrario, si el tipo-id nombra una plantilla de alias con una lista de argumentos de plantilla, el resultado representa el alias de tipo así nombrado. (Otra forma de nombres de alias de tipo sería tratada como un nombre-de-reflexión, y el resultado también representaría el alias de tipo.)
  • De lo contrario, el resultado representa el tipo denotado por el tipo-id.
4) La expresión ^^id-expression representa una entidad determinada de la siguiente manera:
  • Si la expresión-id denota:
la expresión es inválida.
  • De lo contrario, si la expresión-id denota un conjunto de sobrecarga, la resolución de sobrecarga debe seleccionar una función única. El resultado representa esa función.
template<typename T> void fn() requires (^^T != ^^int);
template<typename T> void fn() requires (^^T == ^^int);
template<typename T> void fn() requires (sizeof(T) == sizeof(int));
constexpr std::meta::info a = ^^fn<char>; // OK
constexpr std::meta::info b = ^^fn<int>;  // error: ambiguous

El operando es un operando no evaluado.

Notas

Un valor de reflexión también puede ser producido por std::meta::reflect_constant, std::meta::reflect_object, std::meta::reflect_function, o mediante inicialización por defecto de std::meta::info. Además, se puede obtener un valor de reflexión llamando a funciones <meta> con objetos std::meta::info existentes.

Si un alias de tipo aparece como parte de un tipo-id, el operador de reflexión no preserva el alias de tipo.

using T = int;
static_assert(^^T != ^^int);
static_assert(^^T& == ^^int&);
static_assert(^^T const == ^^const int);

Ejemplo

int arr[] = {1, 2, 3};
auto [a1, a2, a3] = arr;
[[=1]] void fn(int n);
enum Enum { A };
using Alias = int;
struct S { int mem; };
template<auto> struct TCls {};
template<auto> void TFn();
template<auto> int TVar;
template<auto N> using TAlias = TCls<N>;
template<auto> concept Concept = true;
namespace NS {}
namespace NSAlias = NS;

constexpr auto r_arr   = ^^arr; // represents a variable
constexpr auto r_sb    = ^^a3; // represents a structured binding
constexpr auto r_fn    = ^^fn; // represents a function
constexpr auto r_enum  = ^^Enum::A; // represents an enumerator
constexpr auto r_alias = ^^Alias; // represents a type alias
constexpr auto r_type  = ^^S; // represents a type
constexpr auto r_mem   = ^^S::mem; // represents a class member
constexpr auto r_tcls  = ^^TCls; // represents a class template
constexpr auto r_tfn   = ^^TFn; // represents a function template
constexpr auto r_tvar  = ^^TVar; // represents a variable template
constexpr auto r_ttype = ^^TAlias; // represents an alias template
constexpr auto r_cncpt = ^^Concept; // represents a concept
constexpr auto r_ns    = ^^NS; // represents a namespace
constexpr auto r_ns2   = ^^NSAlias; // represents a namespace alias

int main() {}

Véase también

devuelve una reflexión que representa un valor o un objeto parámetro de plantilla, adecuado para usar como argumento de plantilla constante
(plantilla de función)
devuelve una reflexión que representa un objeto, adecuado para usar como argumento de plantilla constante
(plantilla de función)
devuelve una reflexión que representa una función, adecuado para usar como argumento de plantilla constante
(plantilla de función)