Правильное отделение общих перегруженных функций шаблона от специализированных?

Вопрос

  • Каков правильный способ иметь помощники по шаблонам и дополнительные специализированные перегрузки в отдельных файлах, чтобы включения не зависели от порядка?

  • Есть ли правильный способ сделать что-то в ситуациях, подобных моей (см. описание ниже)?

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: я не уверен, что описание составлено правильно. Пожалуйста, не стесняйтесь помочь сформулировать это лучше.

Описание

Код, с которым я работаю, основан на использовании 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;

Я пишу помощник для добавления новых атрибутов, содержащихся в заголовочном файле 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;
}

Я хотел бы расширить этот помощник для класса PointXY в отдельном заголовочном файле 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()));
}

Чтобы использовать помощник для PointXY, мне нужно:

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

Проблемы

Цели

  • Вариантные хелперы и специализированные хелперы должны быть разделены, и пользователь должен включать хелперы только для необходимых классов.

person AMA    schedule 18.06.2018    source источник


Ответы (1)


Я думаю, что использование шаблонного класса со статической функцией вместо набора перегруженных, возможно, шаблонных функций поможет:

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()));
   }
};
person user7860670    schedule 18.06.2018