<cliext/adapter>
(STL/CLR)
El encabezado <cliext/adapter>
STL/CLR especifica dos plantillas de clase (collection_adapter
y ) y range_adapter
la plantilla make_collection
de función .
Sintaxis
#include <cliext/adapter>
Requisitos
Encabezado:<cliext/adapter>
Espacio de nombres: cliext
Declaraciones
Clase | Descripción |
---|---|
collection_adapter |
Encapsula la colección de Biblioteca de clases base (BCL) como un rango. |
range_adapter |
Ajusta el intervalo como una colección de BCL. |
Función | Descripción |
---|---|
make_collection |
Crea un adaptador de rangos mediante un par de iteradores. |
Miembros
collection_adapter
Encapsula una colección de .NET para que se use como contenedor STL/CLR. collection_adapter
es una clase de plantilla que describe un objeto contenedor STL/CLR simple. Encapsula una interfaz de Biblioteca de clases base (BCL) y devuelve un par de iteradores que se usa para manipular la secuencia controlada.
Sintaxis
template<typename Coll>
ref class collection_adapter;
template<>
ref class collection_adapter<
System::Collections::ICollection>;
template<>
ref class collection_adapter<
System::Collections::IEnumerable>;
template<>
ref class collection_adapter<
System::Collections::IList>;
template<>
ref class collection_adapter<
System::Collections::IDictionary>;
template<typename Value>
ref class collection_adapter<
System::Collections::Generic::ICollection<Value>>;
template<typename Value>
ref class collection_adapter<
System::Collections::Generic::IEnumerable<Value>>;
template<typename Value>
ref class collection_adapter<
System::Collections::Generic::IList<Value>>;
template<typename Key,
typename Value>
ref class collection_adapter<
System::Collections::Generic::IDictionary<Key, Value>>;
Parámetros
Coll
Tipo de la colección encapsulada.
Especializaciones
carga de trabajo | Descripción |
---|---|
IEnumerable |
Se mueve en secuencia por los elementos. |
ICollection |
Mantiene un grupo de elementos. |
IList |
Mantiene un grupo ordenado de elementos. |
IDictionary |
Mantiene un conjunto de pares {clave, valor}. |
IEnumerable<Value> |
Se mueve en secuencia por los elementos con tipo. |
ICollection<Value> |
Mantiene un grupo de elementos con tipo. |
IList<Value> |
Mantener un grupo ordenado de elementos con tipo. |
IDictionary<Value> |
Mantiene un conjunto de pares {clave, valor} con tipo. |
Miembros
Definición de tipo | Descripción |
---|---|
collection_adapter::difference_type |
El tipo de una distancia con signo entre dos elementos. |
collection_adapter::iterator |
El tipo de un iterador para la secuencia controlada. |
collection_adapter::key_type |
Tipo de una clave de diccionario. |
collection_adapter::mapped_type |
Tipo de un valor de diccionario. |
collection_adapter::reference |
El tipo de una referencia a un elemento. |
collection_adapter::size_type |
El tipo de una distancia con signo entre dos elementos. |
collection_adapter::value_type |
El tipo de un elemento. |
Función de miembro | Descripción |
---|---|
collection_adapter::base |
Designa la interfaz BCL encapsulada. |
collection_adapter::begin |
Designa el principio de la secuencia controlada. |
collection_adapter::collection_adapter |
Construye un objeto adaptador. |
collection_adapter::end |
Designa el final de la secuencia controlada. |
collection_adapter::size |
Cuenta el número de elementos. |
collection_adapter::swap |
Intercambia el contenido de dos contenedores. |
Operator | Descripción |
---|---|
collection_adapter::operator= |
Reemplaza el identificador de BCL almacenado. |
Comentarios
Esta clase de plantilla se usa para manipular un contenedor de BCL como un contenedor de STL/CLR. collection_adapter
almacena un identificador en una interfaz BCL, que, a su vez, controla una secuencia de elementos. Un objeto collection_adapter
X
devuelve un par de iteradores de entrada, X.begin()
y X.end()
, que se usan para visitar los elementos en orden. Algunas de las especializaciones también permiten escribir X.size()
para determinar la longitud de la secuencia controlada.
collection_adapter::base
Designa la interfaz BCL encapsulada.
Sintaxis
Coll^ base();
Comentarios
La función miembro devuelve el identificador de la interfaz BCL almacenado.
Ejemplo
// cliext_collection_adapter_base.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d6x(6, L'x');
Mycoll c1(%d6x);
// display initial contents "x x x x x x "
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
System::Console::WriteLine("base() same = {0}", c1.base() == %c1);
return (0);
}
x x x x x x
base() same = True
collection_adapter::begin
Designa el principio de la secuencia controlada.
Sintaxis
iterator begin();
Comentarios
La función miembro devuelve un iterador de entrada que designa el primer elemento de la secuencia controlada o apunta inmediatamente después del final de una secuencia vacía.
Ejemplo
// cliext_collection_adapter_begin.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// inspect first two items
Mycoll::iterator it = c1.begin();
System::Console::WriteLine("*begin() = {0}", *it);
System::Console::WriteLine("*++begin() = {0}", *++it);
return (0);
}
a b c
*begin() = a
*++begin() = b
collection_adapter::collection_adapter
Construye un objeto adaptador.
Sintaxis
collection_adapter();
collection_adapter(collection_adapter<Coll>% right);
collection_adapter(collection_adapter<Coll>^ right);
collection_adapter(Coll^ collection);
Parámetros
collection
Identificador BCL que se encapsula.
right
Objeto que se va a copiar.
Comentarios
El constructor:
collection_adapter();
inicializa el identificador almacenado con nullptr
.
El constructor:
collection_adapter(collection_adapter<Coll>% right);
inicializa el identificador almacenado con right.base()
.
El constructor:
collection_adapter(collection_adapter<Coll>^ right);
inicializa el identificador almacenado con right->base()
.
El constructor:
collection_adapter(Coll^ collection);
inicializa el identificador almacenado con collection
.
Ejemplo
// cliext_collection_adapter_construct.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d6x(6, L'x');
// construct an empty container
Mycoll c1;
System::Console::WriteLine("base() null = {0}", c1.base() == nullptr);
// construct with a handle
Mycoll c2(%d6x);
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// construct by copying another container
Mycoll c3(c2);
for each (wchar_t elem in c3)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// construct by copying a container handle
Mycoll c4(%c3);
for each (wchar_t elem in c4)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
base() null = True
x x x x x x
x x x x x x
x x x x x x
collection_adapter::difference_type
Tipos de una distancia con signo entre dos elementos.
Sintaxis
typedef int difference_type;
Comentarios
El tipo describe un recuento de elementos con signo.
Ejemplo
// cliext_collection_adapter_difference_type.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// compute positive difference
Mycoll::difference_type diff = 0;
Mycoll::iterator it = c1.begin();
for (; it != c1.end(); ++it)
++diff;
System::Console::WriteLine("end()-begin() = {0}", diff);
return (0);
}
a b c
end()-begin() = 3
collection_adapter::end
Designa el final de la secuencia controlada.
Sintaxis
iterator end();
Comentarios
La función miembro devuelve un iterador de entrada que apunta inmediatamente después del final de la secuencia controlada.
Ejemplo
// cliext_collection_adapter_end.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
Mycoll::iterator it = c1.begin();
for (; it != c1.end(); ++it)
System::Console::Write("{0} ", *it);
System::Console::WriteLine();
return (0);
}
a b c
collection_adapter::iterator
El tipo de un iterador para la secuencia controlada.
Sintaxis
typedef T1 iterator;
Comentarios
El tipo describe un objeto de tipo sin especificar T1
que puede actuar como un iterador de entrada de la secuencia controlada.
Ejemplo
// cliext_collection_adapter_iterator.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
Mycoll::iterator it = c1.begin();
for (; it != c1.end(); ++it)
System::Console::Write("{0} ", *it);
System::Console::WriteLine();
return (0);
}
a b c
collection_adapter::key_type
Tipo de una clave de diccionario.
Sintaxis
typedef Key key_type;
Comentarios
El tipo es un sinónimo del parámetro Key
de plantilla , en una especialización para IDictionary
o IDictionary<Value>
; de lo contrario, no se define.
Ejemplo
// cliext_collection_adapter_key_type.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/map>
typedef cliext::map<wchar_t, int> Mymap;
typedef cliext::collection_adapter<
System::Collections::Generic::IDictionary<wchar_t, int>> Mycoll;
typedef System::Collections::Generic::KeyValuePair<wchar_t,int> Mypair;
int main()
{
Mymap d1;
d1.insert(Mymap::make_value(L'a', 1));
d1.insert(Mymap::make_value(L'b', 2));
d1.insert(Mymap::make_value(L'c', 3));
Mycoll c1(%d1);
// display contents "[a 1] [b 2] [c 3] "
for each (Mypair elem in c1)
{
Mycoll::key_type key = elem.Key;
Mycoll::mapped_type value = elem.Value;
System::Console::Write("[{0} {1}] ", key, value);
}
System::Console::WriteLine();
return (0);
}
[a 1] [b 2] [c 3]
collection_adapter::mapped_type
Tipo de un valor de diccionario.
Sintaxis
typedef Value mapped_type;
Comentarios
El tipo es un sinónimo del parámetro Value
de plantilla , en una especialización para IDictionary
o IDictionary<Value>
; de lo contrario, no se define.
Ejemplo
// cliext_collection_adapter_mapped_type.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/map>
typedef cliext::map<wchar_t, int> Mymap;
typedef cliext::collection_adapter<
System::Collections::Generic::IDictionary<wchar_t, int>> Mycoll;
typedef System::Collections::Generic::KeyValuePair<wchar_t,int> Mypair;
int main()
{
Mymap d1;
d1.insert(Mymap::make_value(L'a', 1));
d1.insert(Mymap::make_value(L'b', 2));
d1.insert(Mymap::make_value(L'c', 3));
Mycoll c1(%d1);
// display contents "[a 1] [b 2] [c 3] "
for each (Mypair elem in c1)
{
Mycoll::key_type key = elem.Key;
Mycoll::mapped_type value = elem.Value;
System::Console::Write("[{0} {1}] ", key, value);
}
System::Console::WriteLine();
return (0);
}
[a 1] [b 2] [c 3]
collection_adapter::operator=
Reemplaza el identificador de BCL almacenado.
Sintaxis
collection_adapter<Coll>% operator=(collection_adapter<Coll>% right);
Parámetros
right
Adaptador que se copia.
Comentarios
El operador miembro copia right
en el objeto y, a continuación, devuelve *this
. Se usa para reemplazar el identificador de BCL almacenado por una copia del identificador BCL almacenado en right
.
Ejemplo
// cliext_collection_adapter_operator_as.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// assign to a new container
Mycoll c2;
c2 = c1;
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
a b c
a b c
collection_adapter::reference
El tipo de una referencia a un elemento.
Sintaxis
typedef value_type% reference;
Comentarios
El tipo describe una referencia a un elemento.
Ejemplo
// cliext_collection_adapter_reference.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents "a b c "
Mycoll::iterator it = c1.begin();
for (; it != c1.end(); ++it)
{ // get a reference to an element
Mycoll::reference ref = *it;
System::Console::Write("{0} ", ref);
}
System::Console::WriteLine();
return (0);
}
a b c
collection_adapter::size
Cuenta el número de elementos.
Sintaxis
size_type size();
Comentarios
La función miembro devuelve la longitud de la secuencia controlada. No se define en una especialización para IEnumerable
o IEnumerable<Value>
.
Ejemplo
// cliext_collection_adapter_size.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d6x(6, L'x');
Mycoll c1(%d6x);
// display initial contents "x x x x x x "
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
System::Console::WriteLine("size() = {0}", c1.size());
return (0);
}
x x x x x x
size() = 6
collection_adapter::size_type
El tipo de una distancia con signo entre dos elementos.
Sintaxis
typedef int size_type;
Comentarios
El tipo describe un recuento de elementos no negativo.
Ejemplo
// cliext_collection_adapter_size_type.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d6x(6, L'x');
Mycoll c1(%d6x);
// display initial contents "x x x x x x"
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
Mycoll::size_type size = c1.size();
System::Console::WriteLine("size() = {0}", size);
return (0);
}
x x x x x x
size() = 6
collection_adapter::swap
Intercambia el contenido de dos contenedores.
Sintaxis
void swap(collection_adapter<Coll>% right);
Parámetros
right
Contenedor con el que se va a intercambiar el contenido.
Comentarios
La función miembro intercambia los identificadores de BCL almacenados entre *this
y right
.
Ejemplo
// cliext_collection_adapter_swap.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display initial contents " a b c"
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// construct another container with repetition of values
cliext::deque<wchar_t> d2(5, L'x');
Mycoll c2(%d2);
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// swap and redisplay
c1.swap(c2);
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
a b c
x x x x x
x x x x x
a b c
collection_adapter::value_type
El tipo de un elemento.
Sintaxis
typedef Value value_type;
Comentarios
El tipo es un sinónimo del parámetro Value
de plantilla , si está presente en la especialización; de lo contrario, es un sinónimo de System::Object^
.
Ejemplo
// cliext_collection_adapter_value_type.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::collection_adapter<
System::Collections::ICollection> Mycoll;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Mycoll c1(%d1);
// display contents "a b c" using value_type
for (Mycoll::iterator it = c1.begin();
it != c1.end(); ++it)
{ // store element in value_type object
Mycoll::value_type val = *it;
System::Console::Write("{0} ", val);
}
System::Console::WriteLine();
return (0);
}
a b c
make_collection (STL/CLR)
Cree un objeto range_adapter
a partir de un par de iteradores.
Sintaxis
template<typename Iter>
range_adapter<Iter> make_collection(Iter first, Iter last);
Parámetros
Iter
Tipo de los iteradores encapsulados.
first
Primer iterador que se encapsula.
last
Segundo iterador que se encapsula.
Comentarios
La plantilla de función devuelve gcnew range_adapter<Iter>(first, last)
. Se usa para construir un objeto range_adapter<Iter>
a partir de un par de valores.
Ejemplo
// cliext_make_collection.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::deque<wchar_t> Mycont;
typedef cliext::range_adapter<Mycont::iterator> Myrange;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
// display contents " a b c"
for each (wchar_t elem in d1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
System::Collections::ICollection^ p1 =
cliext::make_collection(d1.begin(), d1.end());
System::Console::WriteLine("Count = {0}", p1->Count);
System::Console::WriteLine("IsSynchronized = {0}",
p1->IsSynchronized);
System::Console::WriteLine("SyncRoot not nullptr = {0}",
p1->SyncRoot != nullptr);
// copy the sequence
cli::array<System::Object^>^ a1 = gcnew cli::array<System::Object^>(5);
a1[0] = L'|';
p1->CopyTo(a1, 1);
a1[4] = L'|';
for each (wchar_t elem in a1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
a b c
Count = 3
IsSynchronized = False
SyncRoot not nullptr = True
| a b c |
range_adapter (STL/CLR)
Una clase de plantilla que encapsula un par de iteradores que se usan para implementar varias interfaces de Biblioteca de clases base (BCL). Use el range_adapter para manipular un intervalo STL/CLR como si fuera una colección BCL.
Sintaxis
template<typename Iter>
ref class range_adapter
: public
System::Collections::IEnumerable,
System::Collections::ICollection,
System::Collections::Generic::IEnumerable<Value>,
System::Collections::Generic::ICollection<Value>
{ ..... };
Parámetros
Iter
Tipo asociado a los iteradores encapsulados.
Miembros
Función de miembro | Descripción |
---|---|
range_adapter::range_adapter |
Construye un objeto adaptador. |
Operator | Descripción |
---|---|
range_adapter::operator= |
Reemplaza el par de iteradores almacenados. |
Interfaces
Interfaz | Descripción |
---|---|
IEnumerable | Recorre en iteración los elementos de la colección. |
ICollection | Mantiene un grupo de elementos. |
IEnumerable<T> | Recorre en iteración los elementos con tipo de la colección. |
ICollection<T> | Mantiene un grupo de elementos con tipo. |
Comentarios
range_adapter almacena un par de iteradores, que, a su vez, delimitan una secuencia de elementos. El objeto implementa cuatro interfaces de BCL que permiten recorrer los elementos en orden. Esta clase de plantilla se usa para manipular rangos de STL/CLR de forma muy similar a los contenedores de BCL.
range_adapter::operator=
Reemplaza el par de iteradores almacenados.
Sintaxis
range_adapter<Iter>% operator=(range_adapter<Iter>% right);
Parámetros
right
Adaptador que se copia.
Comentarios
El operador miembro copia right
en el objeto y, a continuación, devuelve *this
. Se usa para reemplazar el par de iteradores almacenados por una copia del par iterador almacenado en right
.
Ejemplo
// cliext_range_adapter_operator_as.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::deque<wchar_t> Mycont;
typedef cliext::range_adapter<Mycont::iterator> Myrange;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
Myrange c1(d1.begin(), d1.end());
// display contents " a b c"
for each (wchar_t elem in c1)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// assign to a new container
Myrange c2;
c2 = c1;
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
a b c
a b c
range_adapter::range_adapter
Construye un objeto adaptador.
Sintaxis
range_adapter();
range_adapter(range_adapter<Iter>% right);
range_adapter(range_adapter<Iter>^ right);
range_adapter(Iter first, Iter last);
Parámetros
first
Primer iterador que se encapsula.
last
Segundo iterador que se encapsula.
right
Objeto que se va a copiar.
Comentarios
El constructor:
range_adapter();
inicializa el par de iteradores almacenados con iteradores construidos predeterminados.
El constructor:
range_adapter(range_adapter<Iter>% right);
inicializa el par de iteradores almacenados mediante la copia del par almacenado en right
.
El constructor:
range_adapter(range_adapter<Iter>^ right);
inicializa el par de iteradores almacenados mediante la copia del par almacenado en *right
.
El constructor:
range_adapter(Iter^ first, last);
inicializa el par de iterador almacenado con first
y last
.
Ejemplo
// cliext_range_adapter_construct.cpp
// compile with: /clr
#include <cliext/adapter>
#include <cliext/deque>
typedef cliext::deque<wchar_t> Mycont;
typedef cliext::range_adapter<Mycont::iterator> Myrange;
int main()
{
cliext::deque<wchar_t> d1;
d1.push_back(L'a');
d1.push_back(L'b');
d1.push_back(L'c');
// construct an empty adapter
Myrange c1;
// construct with an iterator pair
Myrange c2(d1.begin(), d1.end());
for each (wchar_t elem in c2)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// construct by copying another adapter
Myrange c3(c2);
for each (wchar_t elem in c3)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
// construct by copying an adapter handle
Myrange c4(%c3);
for each (wchar_t elem in c4)
System::Console::Write("{0} ", elem);
System::Console::WriteLine();
return (0);
}
a b c
a b c
a b c