Использование сильного typedef в качестве более легкой альтернативы библиотеке Boost Parameter?
Я часто использую мощную утилиту typedef Boost для повышения безопасности моих программ. Например, написав код следующим образом:
BOOST_STRONG_TYPEDEF(int, X)
BOOST_STRONG_TYPEDEF(int, Y)
BOOST_STRONG_TYPEDEF(int, Width)
BOOST_STRONG_TYPEDEF(int, Height)
struct Rect {
Rect(X x, Y y, Width w, Height h);
};
// Usage:
Rect rect(X(10), Y(20), Width(800), Height(600));
Сильный typedef здесь улучшает читаемость кода и безопасность. (Компилятор сообщит об ошибке, если аргументы предоставлены в неправильном порядке, чего бы не было, если все аргументы были int
.)
Мои вопросы:
- Можно ли использовать BOOST_STRONG_TYPEDEF для этой цели? (Документация очень короткая.)
- Есть ли важные причины, чтобы предпочесть библиотеку параметров boost?
Ответы
Ответ 1
С технической точки зрения:
- он работает
- добавляет безопасность типов
Практически говоря:
Я бы не рекомендовал создавать новые типы только для одного параметра функции (если он не является перечислением, специфичным для этой функции), типы должны пронизывать приложение, чтобы избежать использования приемов много раз.
Если типы X
, Y
, Width
и Height
используются во всем приложении, то не только не будет никакого перевода, но ваше приложение будет намного безопаснее и значительно лучше документировано (да... Я типа урод).
Теперь, что касается Boost.Parameters, это совершенно другое.
Boost.Parameters могут (потенциально) добавляться, когда у вас уже есть типы. Честно говоря, хотя я никогда не видел нужды. Когда ваши функции растут настолько громоздкими, что Boost.Parameters требуется для их вызова, вы должны исправить функции, а не добавлять в беспорядок.
Ответ 2
Использование BOOST_STRONG_TYPDEF создает новый тип, где, поскольку библиотека параметров boost предназначена для указания имен параметрам. Это позволяет вам более четко понимать, что делают ваши функции. Например (из документации по ускорению)
#include <boost/parameter/preprocessor.hpp>
namespace graphs
{
BOOST_PARAMETER_FUNCTION(
(void), // 1. parenthesized return type
depth_first_search, // 2. name of the function template
tag, // 3. namespace of tag types
(required (graph, *) ) // 4. one required parameter, and
(optional // four optional parameters, with defaults
(visitor, *, boost::dfs_visitor<>())
(root_vertex, *, *vertices(graph).first)
(index_map, *, get(boost::vertex_index,graph))
(in_out(color_map), *,
default_color_map(num_vertices(graph), index_map) )
)
)
{
// ... body of function goes here...
// use graph, visitor, index_map, and color_map
}
}
Позволяет вам прямо сказать, что ожидается, почти в дизайне по контракту. Однако я считаю, что это усложняет читаемость вашего кода, чтобы сделать его нецелесообразным.
Лично я предпочитаю использовать BOOST_STRONG_TYPEDEF, поскольку он создает новые типы, которые могут использоваться для сопоставления параметров функции или шаблона (опять же из документации по ускорению).