c++c++98name-lookuptemplate-function

Properly separating common template-function overloads from specialized ones?


Question

DISCLAIMER: I am not sure if description is worded well. Please feel free to help phrasing it better.

Description

Code I'm working with relies on using std::vector of boost::variant for storing attributes of some primitives. Example:

BOOST_STRONG_TYPEDEF(std::string, PointName)
BOOST_STRONG_TYPEDEF(double, CoordinateX)
BOOST_STRONG_TYPEDEF(double, CoordinateY)

typedef boost::variant<PointName, CoordinateX, CoordinateY> PointAttribute;
typedef std::vector<PointAttribute> PointAttributes;

BOOST_STRONG_TYPEDEF(std::string, LineName)
BOOST_STRONG_TYPEDEF(double, LineLength)

typedef boost::variant<LineName, LineLength> LineAttribute;
typedef std::vector<LineAttribute> LineAttributes;

I am writing a helper for adding new attributes contained in a header-file VariantHelper.h:

template <typename TValue, typename TVariant, typename TAllocator>
inline void Add(
    std::vector<TVariant, TAllocator>& attributes, 
    const TValue& value) 
{
    attributes.push_back(TVariant(value));
}

template <typename TVariant, typename TValue, typename TAllocator>
inline std::vector<TVariant, TAllocator>& operator<<(
    std::vector<TVariant, TAllocator>& attributes, 
    const TValue& value) 
{
    Add(attributes, value);
    return attributes;
}

I would like to extend this helper for a class PointXY in a separate header-file PointVariantHelper.h:

// forward declaration
template <typename TValue, typename TVariant, typename TAllocator>
inline void Add(
    std::vector<TVariant, TAllocator>& attributes, 
    const TValue& value);

template <typename TVariant, typename TAllocator>
inline void Add(
    std::vector<TVariant, TAllocator>& attributes, 
    const PointXY& pnt)
{
    Add(attributes, CoordinateX(pnt.X()));
    Add(attributes, CoordinateY(pnt.Y()));
}

To use helper for PointXY I need to:

#include "PointVariantHelper.h"
#include "VariantHelper.h"

Problems

Goals


Solution

  • I think the use of template class with static function instead of set of overloaded possibly template functions would do the trick:

    VariantHelperAddHelper.h

    template <typename TValue, typename TVariant, typename TAllocator> 
    struct AddHelper
    {
        static void 
        Do(std::vector<TVariant, TAllocator> & attributes, const TValue & value)
        {
            attributes.push_back(TVariant(value));
        }
    };
    

    VariantHelper.h

    #include "VariantHelperAddHelper.h"
    
    template <typename TValue, typename TVariant, typename TAllocator>
    inline void 
    Add(std::vector<TVariant, TAllocator> & attributes, const TValue & value) 
    {
        AddHelper<TValue, TVariant, TAllocator>::Do(attributes, value);
    }
    

    PointVariantHelper.h

    #include "VariantHelperAddHelper.h"
    
    // specialization for point
    template <typename TVariant, typename TAllocator> 
    struct AddHelper<PointXY, TVariant, TAllocator>
    {
       static void 
       Do(std::vector<TVariant, TAllocator> & attributes, const PointXY & value)
       {
           AddHelper<CoordinateX, TVariant, TAllocator>::Do(
              attributes, CoordinateX(pnt.X()));
           AddHelper<CoordinateY, TVariant, TAllocator>::Do(
              attributes, CoordinateY(pnt.Y()));
       }
    };