es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Utilizando la función de plantilla para acceder a los bytes crudos de los tipos de datos POD y cadenas.

Estoy tratando de crear una plantilla de función que me permita procesar los bytes crudos de un tipo de dato POD y de strings.

Se me ocurrió este enfoque un poco ingenuo (no uso plantillas mucho, y solo puedo escribirlas y usarlas en casos muy simples):

#include <cstdio>

template<typename T>
void PrintBytes(T object)
{
  unsigned char* p = reinterpret_cast<unsigned char*>(&object);
  for (int i = 0; i < sizeof object; i++)
  {
    printf("%02x ", *p++);
  }

  printf("\n");
}

int main()
{
  int a = 10;
  PrintBytes(a);    // funciona como se esperaba      
  short b = 12;
  PrintBytes(b);    // funciona como se esperaba    
  const char* foo = "ABC";
  PrintBytes(foo);  // funciona como se esperaba, pero no hace lo que quiero
  const char bar[] = "ABC";
  PrintBytes(bar);  // funciona como se esperaba, pero no hace lo que quiero
}

Salida

none
0a 00 00 00
0c 00
a4 ac 5b 8c f6 7f 00 00
a4 fb 7f 07 b7 00 00 00

Salida deseada para los últimos dos casos

none
41 42 43
41 42 43

Obviamente, los primeros dos casos funcionan y los últimos dos no porque foo y bar ya son punteros y unsigned char* p = reinterpret_cast&lt;unsigned char*&gt;(&amp;object) debería ser unsigned char* p = object y el sizeof object debería ser strlen(object).

¿Cómo se puede hacer esto con las plantillas de C++? Puedo usar c++17.

Tags:  ,

Answer

  1. Avatar for davy.ai

    Se puede usar una combinación de std::is_pointer y std::enable_if para comprobar si el tipo es un puntero y luego usar strlen en lugar de sizeof si es un puntero. Aquí hay un ejemplo:

    #include <cstdio>
    #include <type_traits>
    
    template<typename t="">
    typename std::enable_if<><t>::value, void>::type
    PrintBytes(T objeto)
    {
      unsigned char* p = objeto;
      for (int i = 0; i < strlen(objeto); i++)
      {
        printf("%02x ", *p++);
      }
    
      printf("\n");
    }
    
    template<typename t="">
    typename std::enable_if<!std::is_pointer<T>::value, void>::type
    PrintBytes(T objeto)
    {
      unsigned char* p = reinterpret_cast<unsigned char*="">(&objeto);
      for (int i = 0; i < sizeof objeto; i++)
      {
        printf("%02x ", *p++);
      }
    
      printf("\n");
    }
    
    int main()
    {
      int a = 10;
      PrintBytes(a);    // funciona como se esperaba      
      short b = 12;
      PrintBytes(b);    // funciona como se esperaba    
      const char* foo = "ABC";
      PrintBytes(foo);  // funciona como se esperaba
      const char bar[] = "ABC";
      PrintBytes(bar);  // funciona como se esperaba
    }
    

    Producción:

    none
    0a 00 00 00
    0c 00
    41 42 43
    41 42 43

Comments are closed.