正确地将常见的 template-function 重载与专门的重载分开?

Properly separating common template-function overloads from specialized ones?

问题

免责声明:我不确定描述是否措辞正确。请随时帮助更好地措辞。

描述

我正在使用的代码依赖于使用 std::vectorboost::variant 来存储一些基元的属性。 示例:

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;

我正在编写一个帮助程序,用于添加包含在 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;
}

我想在单独的 header-file PointVariantHelper.h 中为 class PointXY 扩展此助手:

// 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()));
}

要为 PointXY 使用助手,我需要:

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

问题

目标

我认为使用带有静态函数的模板 class 而不是一组可能重载的模板函数可以解决问题:

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