Использование сильного 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, так как он создает новые типы, "которые можно использовать для сопоставления либо параметров функции, либо шаблона" (опять же из документации повышения).

Другие вопросы по тегам