正确地将常见的 template-function 重载与专门的重载分开?
Properly separating common template-function overloads from specialized ones?
问题
在单独的文件中使用模板助手和额外的专门重载以便包含 order-independent 的正确方法是什么?
像我这样的情况(见下面的描述)有没有正确的处理方法?
免责声明:我不确定描述是否措辞正确。请随时帮助更好地措辞。
描述
我正在使用的代码依赖于使用 std::vector
或 boost::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"
问题
- Header 无法更改包含顺序
- 进行前向声明似乎是 work-around(否则
Add
将无法正确解析)。这个 SO 问题中描述了类似的问题:“Name lookup for overloaded functions defined later”。
目标
- 变体助手和专门的助手应该分开,用户应该只包含所需的 classes
的助手
我认为使用带有静态函数的模板 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()));
}
};
问题
在单独的文件中使用模板助手和额外的专门重载以便包含 order-independent 的正确方法是什么?
像我这样的情况(见下面的描述)有没有正确的处理方法?
免责声明:我不确定描述是否措辞正确。请随时帮助更好地措辞。
描述
我正在使用的代码依赖于使用 std::vector
或 boost::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"
问题
- Header 无法更改包含顺序
- 进行前向声明似乎是 work-around(否则
Add
将无法正确解析)。这个 SO 问题中描述了类似的问题:“Name lookup for overloaded functions defined later”。
目标
- 变体助手和专门的助手应该分开,用户应该只包含所需的 classes 的助手
我认为使用带有静态函数的模板 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()));
}
};