herramienta de conversión de cadenas de enumeración c ++

¿Por qué necesita una herramienta de este tipo para convertir enumeraciones en cadenas y cadenas en enumeraciones?

En demasiados proyectos, es posible que necesitemos colocar algunas etiquetas de enumeración y números enteros en el registro. Si solo imprimimos la matriz, eso no funcionará. Si hay un problema, tenemos que revisar el registro y consultar uno por uno. En este momento, deberíamos ¿Qué debo hacer? Escribir un montón de if else, escribir un montón de interruptores y hacer coincidir los caracteres uno por uno. Solo puedo decir, código de estudiante de primaria, ¿podemos hacer una conversión universal? La respuesta es definitivamente sí.

Diseño de interfaz de cadena de enumeración

Insertar descripción de la imagen aquí

Código

#include <string>
#include <algorithm>
#include <vector>

template<typename E>
class EnumStrings {
    
    
public:
	EnumStrings(std::initializer_list<std::pair<E, std::string> > list) {
    
    
		m_eValue = m_stringValue = list;
		std::sort(m_eValue.begin(), m_eValue.end(), CompareFirst);
		std::sort(m_stringValue.begin(), m_stringValue.end(), CompareSecond);
	}
	inline static std::string ToString(E value) {
    
    
		auto it = std::lower_bound(gSingleton.m_eValue.begin(),
            gSingleton.m_eValue.end(), std::make_pair(value, std::string()), CompareFirst);
		if(it == gSingleton.m_eValue.end() || it->first != value) {
    
    
			assert(false);
			return std::string();
		}
		return it->second;
	}
	inline static E FromString(const std::string& string, E fallback) {
    
    
		auto it = std::lower_bound(gSingleton.m_stringValue.begin(),
            gSingleton.m_stringValue.end(), std::make_pair((E) 0, string), CompareSecond);
		if(it == gSingleton.m_stringValue.end() || it->second != string)
			return fallback;
		return it->first;
	}
private:
	static const EnumStrings gSingleton;

private:
	std::vector<std::pair<E, std::string>> m_eValue; 
    std::vector<std::pair<E, std::string>> m_stringValue;
private:
	inline static bool CompareFirst(const std::pair<E, std::string>& a, const std::pair<E, std::string>& b) {
    
    
        return (a.first < b.first); }
	inline static bool CompareSecond(const std::pair<E, std::string>& a, const std::pair<E, std::string>& b) {
    
    
        return (a.second < b.second); }
};

template<typename E>
inline std::string EnumToString(E value) {
    
     return EnumStrings<E>::ToString(value); }
template<typename E>
inline E StringToEnum(const std::string& string, E fallback) {
    
     return EnumStrings<E>::FromString(string, fallback); }

#define ENUMSTRINGS(E) template<> const EnumStrings<E> EnumStrings<E>::gSingleton
  1. Resumen del mapa mentalInsertar descripción de la imagen aquí
  2. Los datos se almacenan en dos vectores, que almacenan los valores después de la clasificación por enumeración y la clasificación de cadenas, respectivamente.
  3. Dado que es una clase de plantilla, puede declarar cualquier tipo de columna de plantilla como una sola columna, luego solo hay una copia del tipo de enumeración en toda la memoria y un tipo de enumeración corresponde a una copia.
  4. El constructor utiliza una lista inicializada como parámetro, pasa la enumeración y los valores de cadena uno por uno, los clasifica y guarda los valores en el vector.
  5. Como sugiere el nombre, toString usa e para encontrar la cadena correspondiente. Si no puede encontrarla, naturalmente devolverá una cadena vacía.
  6. formString, como su nombre indica, utiliza una cadena para encontrar la enumeración correspondiente. Hay un parámetro interesante aquí, el respaldo, ¿qué significa? Es una retirada, un plan de contingencia. Para decirlo sin rodeos, significa planta B. El significado en sí es devolver el valor alternativo si no se encuentra.
  7. std::lower_bound Esta función está en el algoritmo estándar y su significado es utilizar la búsqueda binaria en la secuencia ordenada y devolver el primer iterador que no sea menor que el elemento de destino. Es decir, el objetivo de búsqueda en la clase de rango especificada es el resultado de la búsqueda >= el valor objetivo.
  8. Instrucciones.
#include <iostream>
#include "EunmStrings.h"
enum ETest
{
    
    
    Login = 0,
    LoginOut,
    KikOut,
    Disconnected,
};

ENUMSTRINGS(ETest) = {
    
    
	{
    
    Login, "login"},
	{
    
    LoginOut, "login out"},
	{
    
    KikOut, "kikout"},
    {
    
    Disconnected, "disconnected"},
};
int main(int argc, char** argv)
{
    
    
    std::cout << "get string ETestf::Login = "
         << EnumToString(Login) << std::endl; // 模板自动推导得到响应的单例
    std::cout << "get enum login = " << (int)StringToEnum("login", Login) << std::endl;
    return 0;
}

producción

obtener cadena ETestf::Login = iniciar sesión
obtener enumeración iniciar sesión = 0

  1. ¿Es posible convertir objetos en cadenas comparando sus tamaños? Por ejemplo, la bandera de tipo int y la conversión chino-inglés de tipo cadena, después de todo, una oración de caracteres en inglés y una oración de caracteres chinos corresponden uno a uno.

Este es solo un artículo sobre análisis de código fuente.

  1. Estas ideas creativas no son algo que la gente común como yo pueda pensar. También intenté mapear para convertir caracteres, matrices en cadenas y claves de matriz correspondientes a valores. Esto es muy peligroso. Tal vez una matriz se salga de los límites. En el caso del mapa, también puedes usar dos, uno para guardar E y otro para guardar la cadena, que también pueden lograr el mismo efecto, pero soy tan estúpido que no puedo pensar en ello.
  2. Lo más esencial no es ninguno de estos. La idea más esencial es que solo habrá una enumeración en un espacio de nombres y no se puede editar si hay más. Redefinición de símbolos, utilizando una enumeración para deducir una instancia de clase de plantilla, correspondiente a un singleton. , llamar a la función de interfaz deriva directamente singletons de diferentes tipos de enumeraciones de la plantilla, obteniendo así los valores reales, lo cual es realmente inteligente.
template<typename E>
inline std::string EnumToString(E value) {
    
     return EnumStrings<E>::ToString(value); }
template<typename E>
inline E StringToEnum(const std::string& string, E fallback) {
    
     return EnumStrings<E>::FromString(string, fallback); }

#define ENUMSTRINGS(E) template<> const EnumStrings<E> EnumStrings<E>::gSingleton
  1. Vector se utiliza en el proyecto para una clasificación única y una eliminación rápida. Las ideas del jefe son bastante avanzadas. Si cambio al mapa, se siente bien, pero es un poco más lento, no mucho más lento. En un proyecto tan grande, La distancia de ingeniería es casi insignificante. Hay un defecto en este diseño. Si mi enumeración se repite, ¿el resultado será correcto? El mapa elimina directamente la duplicación y el vector se conserva, pero siempre solo se encuentra el primer valor que es mayor que el valor y el otro valor nunca se puede leer. Pero esto es un error en sí mismo, así que tenga cuidado al usarlo. ¿Se puede diseñar de modo que se pueda determinar la duplicación de enumeraciones durante la compilación? Aún no estoy muy familiarizado con las funciones de la plantilla. Lo pensaré en el futuro, es un dolor de cabeza.
  2. Finalmente, echemos un vistazo al código fuente. Proviene del proyecto ssr src/common/EnumStrings.h. Puedes visitar githbub-ssr para presenciar el estilo de los grandes, que siempre está lleno de ideas.

Supongo que te gusta

Origin blog.csdn.net/qq_33944628/article/details/125881625
Recomendado
Clasificación