Я объясню, как я вижу класс черт на простом примере.
Определение может быть таким: характеристика позволяет ненавязчиво расширять T.
Образец
Представьте, что вы хотите предоставить геометрическую библиотеку, содержащую концепцию 2D-точки (координаты X, Y). Вы предоставляете
/*
* @tparam T the coordinate type
*/
template <typename T>
class Point2D
{
T _x;
T _Y;
public:
/* some ctors */
/*
* Multiply this point by the given factor.
* @post this._x = factor * this._x
* this._y = factor * this._y
* @return reference to *this.
*/
Point2D<T> operator*=(double factor);
};
Вы выбираете шаблон класса Point2D, чтобы пользователь вашей библиотеки мог выбрать соответствующий тип (double, если требуется точность, int, если он работает с пикселями, ...). В Qt, например, они вводят int в качестве типа координат, что может блокировать ваш проект. Тип T должен предоставить некоторую информацию о концепции типа координат: в вашем классе Point2D вам нужно будет работать с T:
- Получить скалярный тип T можно умножить на (в моем операторе * = я написал double, но это может быть слишком навязчивым)
- Получить строковое представление T
- Сравните 2 T (чтобы реализовать оператор ==) ...
Если вы напишете свой собственный класс Coordinate, вы сможете предоставить все необходимое. Но если пользователь вашей библиотеки хочет использовать int как T, он не может расширить int.
Вот и черты: ваш Point2D будет использовать класс черт CoordTypeTraits. Его цель - «расширить» тип T, чтобы предоставить все, что вам нужно, от T как концепции координат (функция, определение типа ...)
Образец:
typename <typedef T>
struct CoordTypeTraits
{
/*
* Define the scalar type T is multipiable with
*/
// typedef ... ScalarType;
/*
* Check the equality between 2 T, with a given precision
*/
// static bool IsCloseTo(const T& coord1, const T& coord2);
/*
* Return a string representation of T.
*/
// static string ToString(const T& coord);
}
Теперь вы можете получить доступ к необходимой информации о T в своем коде благодаря классу свойств CoordTypeTraits:
/*
* @tparam T the coordinate type
*/
template <typename T>
class Point2D
{
T _x;
T _Y;
public:
/* some ctors */
/*
* @post this._x = factor * this._x
* this._y = factor * this._y
* @return reference to *this.
*/
Point2D<T> operator*=(CoordTypeTraits<T> factor);
const bool operator==(const T& rhs)
{
return CoordTypeTraits<T>.IsCloseTo(*this, rhs);
}
string ToString() const
{
return CoordTypeTraits<T>.ToString();
}
};
Пользователь вашей библиотеки lib будет использовать ваш Point2D с типом, подходящим для него, и он должен предоставить (путем специализации CoordTypeTraits для этого типа) черты, чтобы «добавить» данные концепции координат в T.
Например, с двойным:
typedef Point2D<double> Point_double;
// specialization of CoordTypeTraits for double coordinate type
template<>
struct CoordTypeTraits<double>
{
typedef double ScalarType;
static bool IsCloseTo(const T& coord1, const T& coord2)
{
return (coord1 - coord2 < GetPrecision()) && (coord2 - coord1 < GetPrecision());
}
private:
static const double GetPrecision()
{
return 0.001; // because double is micrometers by convention, and I need nanometer precision
}
static string ToString(const double& coord)
{
return boost::lexical_cast<string>(coord);
}
}
Например, с int:
typedef Point2D<int> Point_int;
// specialization of CoordTypeTraits for double coordinate type
template<>
struct CoordTypeTraits<int>
{
typedef int ScalarType;
static bool IsCloseTo(const T& coord1, const T& coord2)
{
return coord1 == coord2;
}
static string ToString(const int& coord)
{
return boost::lexical_cast<string>(coord);
}
}
Заключение и примечания
Ваша библиотека предоставляет класс Point2D, поэтому пользователь может использовать все предоставляемые вами функции (сравнивать, переводить, вращать и т. Д.). Он может сделать это с любым типом координат, который пожелает, если он предоставит свойства для обработки этого типа в качестве координаты. Обычно библиотеки предоставляют некоторые общие черты (здесь мы предоставляем Point_double и Point_int).
Реплика: я не пытался компилировать, код просто для иллюстрации.
person
Nico
schedule
27.05.2015