16

I often use the Boost strong typedef utility to improve the safety of my programs. For example by writing code like this:

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));

The strong typedef here improves both code readability and safety. (The compiler will report an error if the arguments are provided in the wrong order, which would not have been the case if the arguments were all int.)

My questions are:

  • Is it ok to use BOOST_STRONG_TYPEDEF for this purpose? (The documentation is very brief.)
  • Are there important reasons to prefer the boost parameter library instead?
StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
  • 1
    depends what you mean by 'ok', it compiles and runs I assume, so what is wrong with that. I see your logic behind this, but it seems 'wrong' to me. There is a reason you can name varaibles and paramaters, so having some one explicitly cast there `int` to a `Width` just to pass it to set the parameter `width` seems wrong. Though might be handy to have `set(width w);` etc. with just `int` you can't do that. – thecoshman Feb 09 '12 at 13:05
  • 1
    boost parameter is for named (and even optional) arguments, while BOOST_STRONG_TYPEDEF *will create a new type "name" which will be substitutable for the original type but still of distinct type*. – Gigi Feb 09 '12 at 13:17

2 Answers2

20

Technically speaking:

  • it works
  • it adds type safety

Practically speaking:

I would not recommend creating new types just for the sake of a single function's parameters (unless it is an enum specific to this function), types should permeate the application to avoid casts being used over and over.

If the types X, Y, Width and Height are used throughout the application, then not only will there be no cast, but your application will be much safer and much better documented too (yeah... I am a type freak).

Now, with regard to Boost.Parameters, this is completely different.

Boost.Parameters can (potentially) be added when you have types already in place. Honestly though I never saw the need. When your functions grow so unwieldy that Boost.Parameters is required to call them, you should fix the functions, not add to the clutter.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • I believe named parameters are particularly suited for highly generic libraries that can't decide for their users what should be considered "clutter", and still want to overload the Overload Overwhelming antipattern – sehe May 16 '14 at 05:49
  • Valid use case for boost.parmater in my mind is a factory function with many defaulted parameters – odinthenerd Jun 03 '16 at 14:00
  • @PorkyBrain: In this case, I prefer a `Builder` pattern with named functions. Have the `Builder` be constructed from the minimal set of mandatory arguments and then all optional arguments are passed with named functions. – Matthieu M. Jun 03 '16 at 14:13
2

Using BOOST_STRONG_TYPDEF is creating a new type, where as the boost parameter library is for giving names to parameters. It lets you be more explicit with what your functions take. For example (from the boost documentation)

#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
  }
}

Lets you explicitly say what is expected, almost in a design by contract sort of way. However I find this complicates the readability of your code enough to make it not worth doing.

Personally I prefer to use BOOST_STRONG_TYPEDEF as it creates a new types "that can be used for matching either function or template parameters" (again from the boost documentation).

Jim Jeffries
  • 9,841
  • 15
  • 62
  • 103