Здравствуйте, Аноним, Вы писали:
А>И в чем их смысл? В частности char_traits, например.
В расширении, группировке и обобщении инструментария, относящегося к тому или иному типу.
Допустим, у нас есть некий класс T, и нам потребовалось добавить функциональность — приведение к целому и обратно.
Казалось бы, нет проблем: вводим в его определение три имени:
class T
{
...
public: // convert to/from int
typedef ??? integral_type; // потому что может статься, что int не всегда нас устраивает
integral_type to_integral() const;
static T from_integral(integral_type); // либо конструктор; но производящая функция - это более общее решение
};
Чем это плохо?
1) Если таких классов много, то придётся в каждый из них включить подобную функциональность. А не факт, что можно модифицировать их определения
2) Для простых типов — определения модифицировать нельзя.
Ну ладно, нельзя так нельзя — специально для этого вводятся операции НАД типом, т.е. перегруженные внешние функции.
someint to_integral(const T& src); // тип результата - по желанию.
// Жаль, что пропал идентификатор типа, специфичного для T, ну да фиг с ним
template<class _> void from_integral(someint){} // первичное объявление шаблона
template<> T from_integral<T>(someint src); // и его специализация для конкретного типа
Чем плохи шаблоны функций со свободными (не выводимыми из аргументов) параметрами шаблона — уже говорилось недавно.
Начиная с неоднозначности и нетривиальных приоритетов при выборе той или иной специализации.
И ещё остаются проблемы, связанные с автоматическим приведением типов аргументов. Полагаясь на выведение типа выражения, можно приплыть в неожиданном направлении.
Кроме того, мы получаем россыпь. Ладно конверсия, это всего лишь пара функций. А та же работа с символами, где функций больше десятка?
Кроме того, покуда нет шаблонных typedef'ов и шаблонных же переменных, мы не можем вводить их иным способом, как завести некий вспомогательный класс по шаблону, параметризованному данным типом.
Он и будет являться traits'ом.
// первичное объявление шаблона
template<class XZ> struct integral_traits
{
typedef int inegral_type; // по умолчанию, int
static integral_type to(const XZ& src) { return to_integral(src); }
// по умолчанию, надеемся, что есть глобальная функция
static XZ from(integral_type src) { XZ dst; from_integral(src,dst); return dst }
// по умолчанию, надеемся, что есть глобальная функция с out-параметром
};
template<> struct integral_traits<T> // для нашего любимого, со встроенной функциональностью
{
typedef T::integral_type integral_type;
static integral_type to(const T& src) { return src.to_integral(); }
static T from(integral_type src) { return T::from_integral(src); }
}
Наконец, мы можем действовать довольно изощрённо: если классы T, U, V являются моделью "ВстроенныйКонвертор", то можем обобщить эту специализацию
template<class XZ>
struct integral_traits_embedded
{
typedef XZ::integral_type integral_type;
static integral_type to(const XZ& src) { return src.to_integral(); }
static XZ from(integral_type src) { return XZ::from_integral(src); }
};
template<class XZ>
struct integral_traits_outer
{
typedef int inegral_type; // по умолчанию, int
static integral_type to(const XZ& src) { return to_integral(src); }
static XZ from(integral_type src) { XZ dst; from_integral(src,dst); return dst }
};
template<class XZ>
struct is_embedded_integral_convertor
{
enum { value = ????? }; // для не-конверторов - false
};
// определение этого свойства (ещё один traits!) может быть автоматизированным
// или же у каждого класса-конвертора должна быть своя специализация
template<class XZ>
struct integral_traits : typename boost::mpl::if_c<
is_embedded_integral_convertor<XZ>::value,
integral_traits_embedded<XZ>,
integral_traits_outer<XZ>
>::type
{
};
Здесь мы увидели ещё одно применение traits'ов — а именно, паттерн "Стратегия". Определение (при компиляции) и поведение (при исполнении) окончательной версии integral_traits зависит от того, какая стратегия — integral_traits_embedded | integral_traits_outer — будет выбрана, мы станем пользоваться тем или иным комплектом функций. |