Can You Make Custom Operators in C++

Can you make custom operators in C++?

Yes! (well, sort of)

There are a couple publicly available tools to help you out. Both use preprocessor code generation to create templates which implement the custom operators. These operators consist of one or more built-in operators in conjunction with an identifier.

Since these aren't actually custom operators, but merely tricks of operator overloading, there are a few caveats:

  • Macros are evil. If you make a mistake, the compiler will be all but entirely useless for tracking down the problem.
  • Even if you get the macro right, if there is an error in your usage of the operator or in the definition of your operation, the compiler will be only slightly more helpful.
  • You must use a valid identifier as part of the operator. If you want a more symbol-like operator, you can use _, o or similarly simple alphanumerics.

CustomOperators

While I was working on my own library for this purpose (see below) I came across this project. Here is an example of creating an avg operator:

#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)

IdOp

What started as an exercise in pure frivolity became my own take on this problem. Here's a similar example:

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_>

Key Differences

  • CustomOperators supports postfix unary operators
  • IdOp templates use references rather than pointers to eliminate use of the free store, and to allow full compile-time evaluation of the operation
  • IdOp allows you to easily specify several operations for the same root identifier

Is it possible to make custom operators in C#?

No, C# does not allow custom operators. You can overload certain pre-existing ones, but you cannot create your own like in Haskell or F#.

How to make custom operators in C++

In your code (as it is standard) operator<< is overloaded for a function pointer.

    LogWriter& LogWriter::operator<<(LogWriter& (*pf)(LogWriter& lw)) {...}

lw.endl is not a function pointer, (neither is lw.endl()) in this line:

    lw << "LOG: TEST" << lw.endl;

As a matter of fact endl, at most, is a member function pointer, which behaves differently than a function pointer (pointer to free function).

What you need to so is to make endl a plain function, for example a class-static one.

        static LogWriter& endl(LogWriter& lw);

(Note that even outside this context a function like this taking an argument of the same type doesn't make sense as a member function.)

In this way, the semantics of

    lw << "LOG: TEST" << LogWriter::endl;

Is basically:

    LogWriter::endl( lw << "LOG: TEST" );

Is it possible to create a new operator in c#?

No, it is not possible. You would need to create a method instead

Is it possible to overload operators in C?

No, it is not possible. C does not support operator overloading by the developer.

A custom operator overload in C++ without overhead

It is optimized by MSVC. Look at the generated code for main() (Using /GS- to remove the security check, just to make it clearer):

$LN10:
sub rsp, 120 ; 00000078H
lea r8, QWORD PTR c$[rsp]
lea rdx, QWORD PTR a$[rsp]
lea rcx, QWORD PTR $T1[rsp]
call static Matrix Matrix::tensor_op(Matrix const &,Matrix const &) ; Matrix::tensor_op
mov eax, 1
add rsp, 120 ; 00000078H
ret 0
main ENDP

That's the same number of instructions as GCC. The construction of the intermediate object is elided.

The extra assembly generated on Compiler Explorer is just MSVC adding the code for the operators, in case they're used independently, and are not cleared up when not used. It's probably just a side-effect of it not having direct Assembly output as GCC/Clang do.



Related Topics



Leave a reply



Submit