c++ - 正确地将常见的模板函数重载与专门的重载分开?

标签 c++ c++98 name-lookup template-function

问题

  • 在单独的文件中使用模板助手和额外的专门重载以便包含顺序无关的正确方法是什么?

  • 在类似我的情况下,是否有正确的处理方法(见下文描述)?

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

描述

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

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;

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

我想在单独的头文件 PointVariantHelper.h 中为类 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"

问题

目标

  • 变体助手和专用助手应该分开,用户应该只包含所需类的助手

最佳答案

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

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

关于c++ - 正确地将常见的模板函数重载与专门的重载分开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50907460/

相关文章:

c++ - 用 C++ 编写符合 IEEE-754 标准的双/浮点除法的最快方法是什么?

C++ 新手尝试循环

c++ - Dropbox Djinni 可以与 C++98 一起使用吗

c++ - 名称查找问题,GCC 和 clang 不同意

c++ - 函数体中声明的名称的非限定名称查找

具有嵌套表达式模板的 C++ 类

c++ - Qt - QTimeEdit 作为计时器查看器

c++ - 从 std::vector<std::pair<T,U>> 构造一个 std::map<T,U>

c++ - 模板重载解决问题

c++ - 如果 'C' 公开继承自 'B',B 私自继承自 'A',为什么我不能在 'A' 内部创建 'C' 的对象?