1

Question

  • 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.

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

  • Variant helpers and specialized helpers should be separated and the user should only include helpers for the needed classes
AMA
  • 4,114
  • 18
  • 32

1 Answers1

1

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()));
   }
};
AMA
  • 4,114
  • 18
  • 32
user7860670
  • 35,849
  • 4
  • 58
  • 84