athos athos - 2 months ago 6
C++ Question

What's is BOOST_LOG_DOXYGEN_PASS for in Boost.Log?

There're some strange code in Boost.Log library, for example in BoostFileLogging.cpp, it says

#ifndef BOOST_LOG_DOXYGEN_PASS

#define BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL(z, n, data)\
template< BOOST_PP_ENUM_PARAMS(n, typename T) >\
inline shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(BOOST_PP_ENUM_BINARY_PARAMS(n, T, const& arg))\
{\
return aux::add_file_log((\
aux::wrap_file_name(arg0, typename parameter::aux::is_named_argument< T0 >::type())\
BOOST_PP_COMMA_IF(BOOST_PP_GREATER(n, 1))\
BOOST_PP_ENUM_SHIFTED_PARAMS(n, arg)\
));\
}

BOOST_PP_REPEAT_FROM_TO(1, BOOST_LOG_MAX_PARAMETER_ARGS, BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL, ~)

#undef BOOST_LOG_INIT_LOG_TO_FILE_INTERNAL

#else // BOOST_LOG_DOXYGEN_PASS

/*!
* The function initializes the logging library to write logs to a file stream.
*
* \param args A number of named arguments. The following parameters are supported:
* \li \c file_name The file name or its pattern. This parameter is mandatory.
* \li \c open_mode The mask that describes the open mode for the file. See <tt>std::ios_base::openmode</tt>.
* \li \c rotation_size The size of the file at which rotation should occur. See <tt>basic_text_file_backend</tt>.
* \li \c time_based_rotation The predicate for time-based file rotations. See <tt>basic_text_file_backend</tt>.
* \li \c auto_flush A boolean flag that shows whether the sink should automatically flush the file
* after each written record.
* \li \c target The target directory to store rotated files in. See <tt>sinks::file::make_collector</tt>.
* \li \c max_size The maximum total size of rotated files in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c min_free_space Minimum free space in the target directory. See <tt>sinks::file::make_collector</tt>.
* \li \c scan_method The method of scanning the target directory for log files. See <tt>sinks::file::scan_method</tt>.
* \li \c filter Specifies a filter to install into the sink. May be a string that represents a filter,
* or a filter lambda expression.
* \li \c format Specifies a formatter to install into the sink. May be a string that represents a formatter,
* or a formatter lambda expression (either streaming or Boost.Format-like notation).
* \return Pointer to the constructed sink.
*/
template< typename... ArgsT >
shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > > add_file_log(ArgsT... const& args);

#endif // BOOST_LOG_DOXYGEN_PASS


What's the motivation for this macro? should I enable it or disable it? it's not documented.

Answer

Doxygen is a program that parses source code and generates documentation.

The purpose of this is so that Doxygen sees (and documents) something different from what the real compiler sees.

In this case, Doxygen will see a variadic template, and so the HTML documentation will say something like this:

add_file_log(ArgsT... const& args);

Template parameters:

  • template< typename... ArgsT >

Return type:

shared_ptr< BOOST_LOG_FILE_SINK_FRONTEND_INTERNAL< sinks::text_file_backend > >

The function initializes the logging library to write logs to a file stream.

... and so on

But Boost Log apparently works on compilers that don't support variadic templates, so the real compiler can't see this. What the compiler sees is a bunch of non-variadic templates, something along these lines (though it's not relevant for explaining BOOST_LOG_DOXYGEN_PASS):

template<typename Arg1T> shared_ptr</*snip*/> add_file_log(Arg1T const& arg1);
template<typename Arg1T, typename Arg2T> shared_ptr</*snip*/> add_file_log(Arg1T const& arg1, Arg2T const& arg2);
template<typename Arg1T, typename Arg2T, typename Arg3T> shared_ptr</*snip*/> add_file_log(Arg1T const& arg1, Arg2T const& arg2, Arg3T const& arg3);
// and so on

You wouldn't want a separate documentation entry for each of these, it would just clutter the documentation.