Explain implementation of function call operator in boost value_factory

30 views Asked by At

I am trying to understand the boost implementation of factory design pattern. Boost provides two types of factory one for pointer types and other for value semantics. I am able to understand a little about the template value_factory class. However I am facing difficulty is understanding how operator()(..) is defined outside class and namespace.

Below is the link to complete code: https://github.com/boostorg/functional/blob/7516442815900430cc9c4a6190354e11bcbe72dd/include/boost/functional/value_factory.hpp

Code snippet after removing lot of includes.

#   ifndef BOOST_PP_IS_ITERATING
namespace boost
{
    template< typename T >  class value_factory;

    template< typename T >
    class value_factory
    {
      public:
        typedef T result_type;
        value_factory()
        { }
    }; // value_factory
    
    template< typename T > class value_factory<T&>;
} // namespace boost
#   else // defined(BOOST_PP_IS_ITERATING)
    template< BOOST_PP_ENUM_PARAMS(0, typename T) >
    inline result_type operator()(BOOST_PP_ENUM_BINARY_PARAMS(0, T, &a)) const
    {
        return result_type(BOOST_PP_ENUM_PARAMS(N,a));
    }
#   endif // defined(BOOST_PP_IS_ITERATING)

This code is from boost version 1.71.

I would like to understand how operator()(...) plays role here

  1. It is outside class
  2. It is defined in 2nd conditional block # else // defined(BOOST_PP_IS_ITERATING)

As per my understanding member function operator()(...) should have been inside the class.

1

There are 1 answers

0
Ted Lyngmo On BEST ANSWER

It is defined inside the class. The trick is that the header file is including itself and is using macro-magic to eventually terminate the recursion.

The end of the class definition has this #include BOOST_PP_ITERATE() line and it will recursively #include itself until BOOST_PP_IS_ITERATING is #defined. The result of that inclusion t will go where marked:

#     define BOOST_PP_FILENAME_1 <boost/functional/value_factory.hpp>
#     define BOOST_PP_ITERATION_LIMITS (0,BOOST_FUNCTIONAL_VALUE_FACTORY_MAX_ARITY)
#     include BOOST_PP_ITERATE()              // <- operator() definition goes here

    }; // end of class [my remark]

    template< typename T > class value_factory<T&>;
    // forbidden, would create a dangling reference

} // namespace boost [my remark]

#     define BOOST_FUNCTIONAL_VALUE_FACTORY_HPP_INCLUDED
#   else // defined(BOOST_PP_IS_ITERATING)

// the operator definition in header

If compiled with g++ -E you can also see the result:

namespace boost {

template<class T>
class value_factory;

template<class T>
class value_factory {
public:
    typedef T result_type;



    template<class... Args>
    result_type operator()(Args&&... args) const {
        return result_type(std::forward<Args>(args)...);
    }
# 99 "/home/ted/local/include/boost/functional/value_factory.hpp"
};

template<class T>
class value_factory<T&> { };

}