usar entre diferencia declarar constante como c++ string templates

c++ - entre - declarar char en c



Pasar const char*como argumento de plantilla (4)

Así es como lo hago. Tiene mucho más sentido para mí:

struct MyString { static const std::string val; } const std::string MyString::val = "this is your string"; template<typename T> void func() { std::cout << T::val << std::endl; } void main() { func<MyString>(); }

¿Por qué no puedes pasar cadenas literales aquí? Lo hice funcionar con una solución muy leve.

template<const char* ptr> struct lols { lols() : i(ptr) {} std::string i; }; class file { public: static const char arg[]; }; decltype(file::arg) file::arg = __FILE__; // Getting the right type declaration for this was irritating, so I C++0xed it. int main() { // lols<__FILE__> hi; // Error: A template argument may not reference a non-external entity lols<file::arg> hi; // Perfectly legal std::cout << hi.i; std::cin.ignore(); std::cin.get(); }


Es posible, pero el argumento de la plantilla debe tener un enlace externo, lo que impide usar cadenas literales y mitiga la utilidad de hacer esto.

Un ejemplo que tengo es:

template<const char* name, const char* def_value=empty_> struct env : public std::string { env() { const char* p = std::getenv(name); assign(p ? p : def_value); } }; extern const char empty_[] = ""; std::string test = env<empty_>();


Esto funciona para las clases y, IMO, es útil. La implementación es rápida y sucia, pero se puede limpiar fácilmente:

#include <stdio.h> #include <string.h> struct TextTag { const char *text; }; template <const TextTag &TRUE, const TextTag &FALSE> struct TextTaggedBool { const char *GetAsText() const { return m_value ? TRUE.text: FALSE.text; } void SetByText(const char *s) { m_value = !strcmp(s, TRUE.text); } bool m_value; }; class Foo { public: void method() { m_tbool.SetByText("True!"); printf("%s/n", m_tbool.GetAsText()); m_tbool.SetByText("False!"); printf("%s/n", m_tbool.GetAsText()); m_tbool.m_value = true; printf("%s/n", m_tbool.GetAsText()); m_tbool.m_value = false; printf("%s/n", m_tbool.GetAsText()); } private: static constexpr TextTag TrueTag = { "True!" }; static constexpr TextTag FalseTag = { "False!" }; TextTaggedBool<TrueTag, FalseTag> m_tbool; }; void main() { Foo().method(); }

Salida:

¡Cierto! ¡Falso! ¡Cierto! ¡Falso!


Porque esto no sería una utilidad útil. Como no tienen la forma permitida de un argumento de plantilla, actualmente no funciona.

Supongamos que funcionan. Como no se requiere que tengan la misma dirección para el mismo valor utilizado, obtendrá diferentes instancias aunque tenga el mismo valor literal de cadena en su código.

lols<"A"> n; // might fail because a different object address is passed as argument! lols<"A"> n1 = n;

Puede escribir un complemento para su editor de texto que reemplaza una cadena por una lista separada por comas de literales de caracteres y viceversa. Con plantillas variadic, podría "resolver" ese problema de esta manera, de alguna manera.