Saltar a contenido

Última actualización:2026-10-12

Vinculaciones estructuradas en C++17

Antes de hablar de las vinculaciones estructuradas, aquí van varias preguntas de entrevista: ¿sabrías responderlas?

  • ¿Cómo usar las vinculaciones estructuradas para acceder a los miembros privados de una clase propia?

  • ¿Cómo usar las vinculaciones estructuradas para modificar los miembros de una clase propia?

Pocas personas sabrán responder estas preguntas, y ni los enunciados ni las respuestas se encuentran en internet. A partir de estos problemas surge el contenido de este artículo: cómo dar soporte a las vinculaciones estructuradas para tipos propios, y qué trampas esconde.

Nota: versión para impacientes, las respuestas y el código ya están en el Planeta.

Para que el contenido de este artículo fluya mejor, partiremos de un ejemplo.

1.Tipos propios

Dada una clase:

struct Foo {
  Foo(int64_t id, std::string data) : id_(id), data_(std::move(data)) {}
  void Print() { std::cout << "id = " << id_ << ", data = " << data_ << std::endl; }

 private:
  int64_t id_;
  std::string data_;
};

Para hacer que este código funcione:

int main() {
  Foo f{12, "hello world"};
  const auto& [id, data] = f;
  std::cout << "id = " << id << ", data = " << data << std::endl;
  f.Print();
}

Si se ejecuta directamente, no compila:

 cannot decompose inaccessible member 'Foo::id_' of 'const Foo'
   42 |   const auto& [id, data] = f;

¿Qué hacer entonces?

2.Dar soporte a las vinculaciones estructuradas

Este problema lo resolvemos en dos pasos:

1.Especializar std::tuple_size y std::tuple_element

namespace std {
  template <>
  struct tuple_size<Foo> : std::integral_constant<std::size_t, 2> {};

  template <>
  struct tuple_element<0, Foo> {
    using type = int64_t;
  };

  template <>
  struct tuple_element<1, Foo> {
    using type = std::string;
  };
}

2.Añadir a la estructura anterior una función get amiga y luego implementarla:

template <std::size_t Index>
decltype(auto) get(const Foo& f);

template <>
decltype(auto) get<0>(const Foo& f) {
  return f.id_;
}

template <>
decltype(auto) get<1>(const Foo& f) {
  return f.data_;
}

Con esto ya funciona con normalidad, y se obtiene la salida:

id = 12, data = hello world
id = 12, data = hello world

Para terminar, dejo planteadas varias preguntas:

  • Arriba se proporciona acceso de solo lectura; ¿qué ocurre si, al acceder, se modifica con const auto &?

Por ejemplo:

auto& [id, data] = f;
  • ¿Cómo dar soporte al acceso con modificación a los miembros de la clase?

Es decir, lograr que esta instrucción se ejecute con normalidad

auto& [id, data] = f;

Bien, esto es todo por esta sección; nos vemos en la zona de comentarios.

Temas relacionados

Comentarios