Goal:
Describe a way to provide function calls in such a way that for a given function "T F(T a, T b)" an expression "E" written in the code as "aEb" calls the function as "F(a, b)"!
Motivation:
To provide abbreviated forms of function calls, when a certain syntax would increase clarity of the code versus the standard form.
Example:
#include <iostream>
#include <random>
#include <valarray>
using namespace std;
constexpr unsigned int SIDES = 20u;
random_device RNDNGEN;
uniform_int_distribution<unsigned int> DICE[SIDES];
// Function to be called via in-order
unsigned int operatorD(unsigned int number, unsigned int sides)
{
valarray<unsigned int> dice(number);
for(unsigned int & i : dice)
{
i = DICE[sides](RNDNGEN);
}
return dice.sum();
}
int main()
{
// desired call syntax
int x = 1 + 1d6; // executes operator=(x, operator+(1, operatorD(1, 6)))
cout << x << endl; // displays a number in [2, 7]
}
Note that the chosen expression d cannot collide with the expression "1.d", as the dot is required for that and the d may not be followed by a number.
Whether or not the function's name and symbolising expression (in the example "operatorD" and "d") need to be identical is of minor interest; it would be a bonus if both cases were possible.
Failed Solution Attempts:
1) Operator definition
Operator definition is not a functionality of C++ as explained here.
2) Macro definition
The #define directive does not support explicit parameter definitions:
#define (x)D(y) D(x,y)
// error: macro names must be identifiers
#define xDy D(x,y)
// does not recognise x and y as variables
Possible Solutions I do not really want to use:
1) operator overloads with a function object as described here
Triples the number of true function calls for every apparent call.
Related Problems:
Access a one-dimensional array M as a matrix with syntax 'x = M[row][column]'. It would be necessary to define two overloads of operator[] for two different classes of object: a matrix and a vector (either row or column). One 'M[row][column]' call then creates an anonymous vector from M[row], on which [column] is executed. ... Every single 'M[row]' call then generates an object from constructor, on which its own member function operator[] is called exactly once, then it is (being anonymous) immediately discarded.
Use matrix operations in quasi-mathematic notation:
class Matrix
{
Matrix invert();
Matrix transpose();
};
Matrix m;
// m = m.invert();
m = m^-1; // Assuming here that the whole "^-1" were the call sign.
m = m sup-1; // Assuming here that the whole "sup-1" were the call sign.
// m = m.transpose();
m = m^T; // Dito here; the 'T' is not supposed to be a separate Token.
m = m supT; // This should work in spite of operator^, as it would not be defined for a custom Matrix class.
Hide encapsulation of objects:
class Value
{
member x;
};
class EncapsulatedValue<Value T>
{
T value;
EncapsulatedValue(T value) : value{value}
{}
member x()
{
member y = T.x;
/* modifies y */
return y;
}
};
Value temp;
EncapsulatedValue v(temp);
member z;
// z = v.x();
z = v.x;