Reflexão no C++26

Postado em 17/07/2026

Índice

Com a chegada do C++26, as propostas sobre reflexão em tempo de compilação que vinham sendo discutidas a algum tempo (ex: P2996, P3096, P3293, P3394, P3795), finalmente estão se tornando realidade, criando uma nova forma de se programar na linguagem. Na data de escrita deste artigo apenas o GCC 16 tem implementado o suporte experimental. No Clang ainda segue como planejado. Vamos explorar alguns casos de uso dessa funcionalidade.

Operadores novos

Sintaxe Nome Significado
^^entidade Operador de reflexão Converte uma entidade C++ em std::meta::info.
[: reflexão :] Splice Converte uma reflexão novamente em código ou entidade C++.
obj.[: membro :] Splice de membro Acessa o membro descrito pela reflexão.
[: tipo :] variável Splice de tipo Usa o tipo descrito pela reflexão.
[: valor :] Splice de expressão Produz o valor ou entidade refletida.

Obtendo o nome de um tipo

#include <meta>
#include <print>

struct Pessoa {
    int idade;
};

int main() {
    constexpr std::meta::info reflexao = ^^Pessoa;
    std::println("{}", std::meta::identifier_of(reflexao));
    return 0;
}

Saída:

Pessoa

Percorrendo os campos de uma estrutura

#include <meta>
#include <print>

struct Pessoa {
    int idade;
    double altura;
    bool ativo;
};

int main() {
    constexpr auto contexto =
        std::meta::access_context::current();

    template for (
        constexpr auto membro :
        std::define_static_array(
            std::meta::nonstatic_data_members_of(^^Pessoa, contexto)
        )
    ) {
        std::println("{}", std::meta::identifier_of(membro));
    }

    return 0;
}

Saída:

idade
altura
ativo

Mostrar o nome e o tipo de cada campo

#include <meta>
#include <print>

struct Produto {
    int codigo;
    double preco;
    bool disponivel;
};

int main() {
    constexpr auto contexto =
        std::meta::access_context::current();

    template for (
        constexpr auto membro :
        std::define_static_array(
            std::meta::nonstatic_data_members_of(^^Produto, contexto)
        )
    ) {
        constexpr auto tipo_do_membro =
            std::meta::type_of(membro);

        std::println(
            "{}: {}",
            std::meta::identifier_of(membro),
            std::meta::display_string_of(tipo_do_membro)
        );
    }

    return 0;
}

Saída:

codigo: int
preco: double
disponivel: bool

Converter um enum para texto

#include <meta>
#include <print>
#include <string_view>
#include <type_traits>

enum class Cor {
    vermelho,
    verde,
    azul
};

template <typename E>
    requires std::is_enum_v<E>
constexpr std::string_view enum_para_texto(E valor) {
    template for (
        constexpr auto enumerador :
        std::define_static_array(std::meta::enumerators_of(^^E))
    ) {
        if (valor == [: enumerador :]) {
            return std::meta::identifier_of(enumerador);
        }
    }

    return "valor desconhecido";
}

int main() {
    std::println("{}", enum_para_texto(Cor::vermelho));
    std::println("{}", enum_para_texto(Cor::verde));
    std::println("{}", enum_para_texto(Cor::azul));
    return 0;
}

Saída:

vermelho
verde
azul

Adicionando metadados tipados a elementos

#include <meta>
#include <print>

[[=42]]
int resposta;

consteval int valor_da_anotacao()
{
    auto anotacoes =
        std::meta::annotations_of(^^resposta);

    return std::meta::extract<int>(anotacoes[0]);
}

static_assert(valor_da_anotacao() == 42);

int main()
{
    constexpr int valor = valor_da_anotacao();
    std::println("Anotação: {}", valor);
    return 0;
}

Saída:

Anotação: 42

Outros casos de uso

Além das demonstrações exibidas até agora, há uma variedade de outras possibilidades a se explorar. O Daniel Lemire fez uma ótima publicação em seu blog demonstrando a importância da reflexão ao se trabalhar com JSON e SQL.

Referência: cppreference