Да! (ну вроде)
Существует пара общедоступных инструментов, которые могут вам помочь. Оба используют генерацию кода препроцессора для создания шаблонов, которые реализуют пользовательские операторы. Эти операторы состоят из одного или нескольких встроенных операторов в сочетании с идентификатором.
Поскольку это на самом деле не пользовательские операторы, а всего лишь приемы перегрузки операторов, есть несколько предостережений:
- Макросы - это зло. Если вы допустите ошибку, компилятор будет практически бесполезен для отслеживания проблемы.
- Даже если вы правильно понимаете макрос, если в вашем использовании оператора или в определении вашей операции есть ошибка, компилятор будет лишь немного более полезным.
- Вы должны использовать действительный идентификатор как часть оператора. Если вам нужен более символоподобный оператор, вы можете использовать
_
, o
или аналогичные простые буквенно-цифровые символы.
Пока я работал для этой цели над собственной библиотекой (см. Ниже), я наткнулся на этот проект. Вот пример создания оператора avg
:
#define avg BinaryOperatorDefinition(_op_avg, /)
DeclareBinaryOperator(_op_avg)
DeclareOperatorLeftType(_op_avg, /, double);
inline double _op_avg(double l, double r)
{
return (l + r) / 2;
}
BindBinaryOperator(double, _op_avg, /, double, double)
То, что начиналось как упражнение с чистой легкомыслием , стало моим собственным решением этой проблемы. Вот похожий пример:
template<typename T> class AvgOp {
public:
T operator()(const T& left, const T& right)
{
return (left + right) / 2;
}
};
IDOP_CREATE_LEFT_HANDED(<, _avg_, >, AvgOp)
#define avg <_avg_>
Ключевые отличия
- CustomOperators поддерживает унарные операторы postfix
- В шаблонах IdOp используются ссылки, а не указатели, чтобы исключить использование бесплатного хранилища и обеспечить полную оценку операции во время компиляции
- IdOp позволяет вам легко указать несколько операций для одного и того же корневого идентификатора