Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


5.2.1  Facetas

§1 Sinopsis

En la sección anterior ( 5.2) hemos indicado que los datos y funcionalidades de los localismos C++, están encapsulados en clases denominadas facetas ("Facets"), de las que hay seis tipos básicos que rememoran las categorías C representadas por las constantes manifiestas LC_NUMERIC, LC_TIME, LC_MONETARY, LC_CTYPE, LC_COLLATE y LC_MESSAGES. Los nombres respectivos en C++ son: numerictime, monetary, ctype, collate y message.

§2  Clasificación

Las facetas C++ se clasifican en seis categorías básicas representadas por constantes enteras cuyos nombres son los indicados (§1 ).  Aunque también pueden pertenecer a cualquier combinación de bits entre ellas. Dos de estas combinaciones tienen nombres específicos:  none (ninguna) y all (todas).

Los valores particulares asignados a estas constantes dependen de la implementación. A título de ejemplo mostramos un conjunto de valores posibles:

// Nombre Valor    Patrón de bits

collate  = 1;      // 00000001

ctype    = 2;      // 00000010

monetary = 4;      // 00000100

numeric  = 8;      // 00001000

time     = 16;     // 00010000

messages = 32;     // 00100000

Aparte de las dos combinaciones con nombre propio:

none     = 0;      // 00000000

all      = 63      // 00111111


Puede existir cualquier otro tipo que sea combinación de los anteriores y que se identificaría por su valor. Por ejemplo, el valor 12 correspondería al tipo numeric-monetary, y el valor 9 al tipo collate-numeric-monetary.  Observe que el tipo all puede definirse como ( 4.9.3):

all = (collate | ctype | monetary | numeric | time | message );

§3  Las facetas estándar

A continuación se incluye una breve descripción de las categorías básicas. Observe que en realidad las facet estándar son clases genéricas (plantillas 4.12.2). En la descripción que sigue, una expresión como num_get<charT,InputIterator> significa que la faceta num_get es una plantilla que acepta dos argumentos:  un tipo carácter (charT) y un iterador de entrada (InputIterator 5.1.2).  Observe que muchas de las facetas estándar están desdobladas en dos clases que aceptan respectivamente iteradores de entrada y de salida, según el tipo de operación que soportan.

Categoría Facetas incluídas
numeric numpunct<char>,               numpunct<wchar_t>, num_get<char>,                num_get<wchar_t> num_put<char>,                num_put<wchar_t>
time time_get<char>,               time_get<wchar_t>, time_put<char>,               time_put<wchar_t>
monetary moneypunct<char>,             moneypunct<wchar_t> moneypunct<char,true>,        moneypunct<wchar_t,true>, money_get<char>,              money_get<wchar_t> money_put<char>,              money_put<wchar_t>
ctype ctype<char>,                  ctype<wchar_t> codecvt<char,char,mbstate_t>, codecvt<wchar_t,char,mbstate_t>
collate collate<char>,                collate<wchar_t>
messages messages<char>,               messages<wchar_t>
§3.1 Numeric

Las facetas num_get<charT, InputIterator> y num_put<charT, OutputIterator> manejan el formateo numérico. Estas clases disponen de métodos get() y put() en versiones para los tipos long, double, etc. La faceta numpunct<charT> especifica la puntuación de los formatos numéricos. Para ello dispone de métodos como decimal_point(), thousands_sep(), etc.

§3.2  Time

Las clases time_get<charT, InputIterator> y time_put<charT, OutputIterator> manejan los localismos relativos a fecha y hora.  Disponen de métodos como get_time(), get_date(), get_weekday(), etc.

§3.3  Monetary

Las clases money_get<charT, InputIterator> y money_put<charT, OutputIterator> manejan los localismos monetarios. Disponen de métodos get() y put() cuya finalidad es respectivamente analizar o generar una secuencia de dígitos representando una cantidad en fracción monetaria más pequeña la moneda correspondiente. Por ejemplo: la secuencia $1,056.23 en un localismo estándar USA puede traducirse en el número 105623 (centavos de Dolar USA) o en la cadena de caracteres "105623".

La plantilla moneypunct<charT, bool> asume con las cantidades monetarias un papel análogo al de la clase numpunct<charT> con los formatos numéricos. Dispone de métodos como curr_symbol(), etc.

§3.4  Ctype

La clase ctype<charT> encapsula las funcionalidades de clasificación de caracteres mediante métodos como tolower(), toupper(), isspace(), isprint(), etc.  La faceta codecvt<internT, externT, stateT> permite la conversión entre distintos sistemas de codificación. Por ejemplo, del sistema JIS a Unicode ( 2.2.1a0).  Sus métodos principales son in() y out(). Existe una especialización de esta plantilla codecvt<wchar_t, char, mbstate_t> que realiza conversiones de sistema multibyte a caracteres anchos.

§3.5  Collate

La clase collate<charT> permite operaciones de ordenación y comparación de cadenas de caracteres, mediante métodos como compare(), hash() o transform().

§3.6  Messages

La faceta messages<charT> implementa la especificación del consorcio X/Open para inclusión de mensajes en los programas (recordemos que la internacionalización aconseja mantener los mensajes fuera del cuerpo del ejecutable 5.2). Dispone de funciones del tipo open() y close() para mantener catálogos de mensajes.  También para recuperarlos individualmente mediante funciones como get(..., int msgid,...).

§4  Acceder a los locales

Una interesante característica de los locales es la forma en que se acceden sus facetas. Esto no se realiza como cabría esperar mediante un método de la clase locale, sino mediante un par de funciones externas (definidas en la cabecera <locale>), que aceptan un locale como argumento. Es posible determinar si un objeto determinado contiene una faceta mediante la función has_facet(). A su vez la función use_facet() devuelve una referencia a la faceta para que pueda ser utilizada.

Como la mayoría de entidades de la LE, ambas funciones (en realidad son funciones genéricas), están definidas en el subespacio std.

§4.1  use_facet()

Prototipo

template <class Facet> const Facet& use_facet(const locale& loc);

Este método devuelve una referencia a la faceta Facet señalada en el argumento de la plantilla. La faceta se especifica incluyéndola explícitamente en el argumento de la plantilla (ver ejemplo). Si el tipo señalado por Facet no está presente en el objeto loc, (o en su defecto, en el locale gobal), la función lanza una excepción bad_cast ( 1.6.1a) en caso contrario devuelve una referencia a la faceta, que permanece válida mientras exista una copia del locale loc utilizado.

Ejemplo (sin incluir ningún dispositivo de control de las posibles excepciones):

#include <locale>

#include <iostream> using namespace std;

 

int main () {       // ==========

   locale loc;

   const ctype<char>& ct = use_facet<ctype<char> >(loc); // M2:

   cout << 'a' << ct.toupper('c') << endl;     // -> aC

   return 0;

}

Comentario:

En este caso se construye una referencia ct a la faceta ctype para los tipos char y se inicia con el valor devuelto por la función use_facet.  A continuación se utiliza el método toupper() del objeto ct para transformar un carácter minúscula a mayúscula.

Observe el espacio entre los símbolos >  > de la sentencia M2, que es necesario para que el compilador pueda distinguirlos del operador >>.  Esta invocación de la función genérica use_facet utiliza la sintaxis que hemos denominado instanciación implícita específica ( 4.12.1)

De los tres compiladores probados:  Borland C++ 5.5;  MS Visual C++ 6.0 y GNU cpp 2.95.2, solo el de Borland compila el ejemplo sin problemas.  El manual Borland señala que si el compilador no soporta este tipo de instanciación específica (una característica relativamente nueva del lenguaje que no está totalmente implementada en muchos compiladores), es preciso utilizar una sintaxis alternativa, correspondiente a una versión sobrecargada de la anterior que si puede ser soportada por el compilador:

template <class Facet> const Facet& use_facet(const locale& loc, Facet* pf);

En este supuesto, la sentencia M2 del ejemplo quedaría como sigue:

const ctype<char>& ct = use_facet(loc,(ctype<char>*)0);

Obsérvese que como segundo argumento se pasa un puntero nulo (valor 0) al que se ha aplicado un modelado ( 4.9.9) para adaptarlo al tipo esperado por esta nueva versión de use_facet.

§4.2  has_facet()

Prototipo:

template <class Facet> bool has_facet(const locale&) throw();

Esta función permite establecer si un locale tiene un tipo determinado de faceta. Devuelve cierto (true) en caso afirmativo, y falso (flase) en caso contrario. Como en el caso anterior, la instanciación debe realizarse con indicación explícita del tipo a utilizar por la plantilla.

Ejemplo:

#include <locale>

...

using namespace std;

cout << ((has_facet<ctype<char> >(L1)) ? "Si" : "NO") << endl; // -> Si