What is a proper way of having template helpers and additional specialized overloads in separate files so that includes are order-independent?
Is there a proper way of doing things in the situations similar to mine (see description below)?
DISCLAIMER: I am not sure if description is worded well. Please feel free to help phrasing it better.
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
Add
will not resolve properly otherwise). Similar problem is described in this SO question: "Name lookup for overloaded functions defined later".Goals
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()));
}
};