Использование сильного typedef в качестве более легкой альтернативы библиотеке параметров Boost?
Я часто использую Boost strong typedef для повышения безопасности моих программ. Например, написав такой код:
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?
2 ответа
Технически говоря:
- оно работает
- это добавляет безопасность типа
Практически говоря:
Я бы не рекомендовал создавать новые типы только для параметров одной функции (если это не перечисление, специфичное для этой функции), типы должны проникать в приложение, чтобы избежать многократного использования приведений.
Если типы X
, Y
, Width
а также Height
используются во всем приложении, тогда не только не будет приведений, но и ваше приложение будет намного безопаснее и лучше документировано (да... Я просто урод).
Теперь, что касается Boost.Parameters, это совершенно другое.
Boost.Parameters (потенциально) могут быть добавлены, когда у вас уже есть типы. Честно говоря, хотя я никогда не видел в этом необходимости. Когда ваши функции становятся настолько громоздкими, что для их вызова требуется Boost.Parameters, вы должны исправить функции, а не добавлять их в беспорядок.
Использование BOOST_STRONG_TYPDEF создает новый тип, где в качестве библиотеки параметров буста используется для присвоения имен параметрам. Это позволяет вам быть более ясным с тем, что берут ваши функции. Например (из документации по бусту)
#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, так как он создает новые типы, "которые можно использовать для сопоставления либо параметров функции, либо шаблона" (опять же из документации повышения).