У меня есть собственный компаратор, который берет другой компаратор и применяет дополнительную проверку:
template <template <typename> class Comparator, typename T>
struct SoftOrder : public std::binary_function<T, T, bool> {
bool operator()(const T lhs, const T rhs) const {
return Comparator<T>()(lhs, rhs) && AnotherCheck();
}
};
У меня есть второй класс, который принимает компаратор, например.:
template <template <typename> class Comparator>
class Processor {... };
Легко создать экземпляр Processor
со стандартным компаратором (, например.std::less
)вот так:
Processor<std::less> processor1;
Processor<std::greater> processor2;
Однако создать экземпляр с SoftOrder
не так просто, поскольку компилятор правильно жалуется на отсутствие второго аргумента шаблона:
Processor<SoftOrder<std::less> > processor3; // <-- Fails to compile
Я придумал несколько решений, прежде чем опубликовать этот вопрос.
template <typename T>
struct SoftOrderLessThan : public SoftOrder<std::less, T> {};
template <typename T>
struct SoftOrderGreaterThan : public SoftOrder<std::greater, T> {};
Основным недостатком этого решения является необходимость создавать новую структуру каждый раз, когда требуется новый вариант, например.:
template <typename T>
struct SoftOrderLessThan : public SoftOrder<std::less, T> {}; // Never used after the next line.
Processor<SoftOrderLessThan> processor3;
template <template <typename> class Comparator>
struct BindToSoftOrder {
template <typename T>
struct type : public SoftOrder<Comparator, T> {};
};
Это немного лучше, поскольку нам не нужно явно создавать промежуточные классы :
Processor<BindToSoftOrder<std::less>::type> processor3;
. Недостатком является требование класса, специализированного для этой ситуации, который нельзя действительно обобщить, сделав SoftOrder
параметром шаблона для BindToSoftOrder
, поскольку это сделало бы его template<template<template>>>
, что не разрешено стандартом.
template <typename T>
using SoftOrderLessThan = SoftOrder<std::less, T>;
Лучше, чем первый вариант, поскольку он не требует введения новых классов, однако по-прежнему требует замусоривания кода этим дополнительным кодом, который используется только при переходе к другому классу шаблона :
template <typename T>
using SoftOrderLessThan = SoftOrder<std::less, T>; // Never used again
Processor<SoftOrderLessThan> processor3;
Есть ли общий способ привязать мой пользовательский компаратор к конкретному компаратору следующим образом?
Processor<SomeCoolMetaTemplateBind<SoftOrder, std::less>::type> processor3;
Я считаю, что если бы все параметры шаблона были простыми типами, я мог бы просто сделать что-то вроде Processor<boost::mpl::bind<SoftOrder, std::less> >
, но присутствие типа шаблона в списке параметров шаблона предотвращает это.
Идеальное решение было бы связано с C++03, но я также рад услышать решения C++11.
Если нельзя, то надеюсь хотя бы вопрос был интересен.