c++11templatesfactorymember-functionsboost-functional

Explain implementation of function call operator in boost value_factory


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.


Solution

  • 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&> { };
    
    }