目标:
描述一种提供函数调用的方法,使得对于给定的函数" T F(T a,T b)"表达" E"在代码中写成" aEb"将该功能称为" F(a,b)"!
动机:
提供缩写形式的函数调用,当某种语法会增加代码与标准格式的清晰度时。
示例:
#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]
}
请注意,所选表达式d不能与表达式&#34; 1.d&#34;碰撞,因为该点需要点,而d后面可能没有数字。
函数的名称和符号化表达式(在示例&#34; operatorD&#34;&#34; d&#34;)中是否需要相同是不太重要的;如果两种情况都可能,那将是一个奖励。
失败的解决方案尝试:
1)运营商定义
运算符定义不是C ++的功能,如here所述。
2)宏定义
#define指令不支持显式参数定义:
#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
可能的解决方案我真的不想使用:
1)运算符使用如here
所述的函数对象重载每次明显调用的真函数调用次数增加三倍。
相关问题:
使用语法&#39; x = M [row] [column]&#39;访问一维数组M作为矩阵。 有必要为两个不同类别的对象定义operator []的两个重载:矩阵和向量(行或列)。 一个M [行] [列]&#39;然后,调用从M [row]创建一个匿名向量,在该行上执行[column]。 ......每一个&#39; M [row]&#39;然后调用从构造函数生成一个对象,在其上只调用一次自己的成员函数operator [],然后立即丢弃(匿名)。
在准数学符号中使用矩阵运算:
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.
隐藏对象的封装:
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;
答案 0 :(得分:0)
你不能在内置类型(或原始指针)的参数上重载运算符。
除此之外,您可以随心所欲地做任何事情。
问题是什么?
答案 1 :(得分:0)
这只是部分答案,但可能会因额外输入而改善 来自Yakk和sp2danny的指针给我带来了这么远。
可以通过以这种方式定义用户文字来部分解决骰子示例:
unsigned int operator"" d6(unsigned long long int number)
{
return operatorD(number, 6u);
}
显然,operatorD可以完全在这个文字定义中实现,因此不需要引入额外的运行时开销。
这确实可以称为:
unsigned int x = 4 + 3d6;
但请注意,当运算符“”名称不以下划线开头时,g ++将发出警告,标准化委员会保留所有未加前缀的名称。
缺少的部分在于必须将operatorD的第二个参数(要抛出的骰子的边)编码到文字标签中,即:明确地定义所有可用作文字的骰子。
使用这种技术似乎不可能在两侧使用变量实现,例如在operator +上看到的实现:
unsigned int operator"" d(unsigned long long int number, unsigned long long int sides) // Parameters like on operator+
{
return operatorD(number, sides);
}
// error: [...] has invalid argument list
正如定义前缀而不是后缀似乎不是:
unsigned int operator"" d(unsigned long long int size, int) // Parameters like on postfix operator++
{
return operatorD(1, size);
}
// same error
// Comparing the d6 variant with operator++ signature already provided a dead giveaway:
// The postfix operator++ has the spoof parameter, the postfix user literal does not.
有趣的是,使用如展示here的可变参数模板确实应该允许定义具有任意数量参数的后序操作符。
为了完全解决这个例子,仍然需要产生一个适用于任意数量边的代码,以便例如写入“3d13”并没有突然失败,因为之前没有明确宣布过“d13”后缀。
通过使用表达式模板和以here描述的方式重载operator [],可以独立于此解决上述但未解释的第一个矩阵示例。
其他提到的矩阵示例可以通过单个用户定义的后缀来解决:
Matrix operator"" T(Matrix & m)
{
return m.transpose();
}
如果只有用户文字可以定义为类而不仅仅是基元。
到目前为止,已有四分之一;最好的例子至少部分解决了...
但肯定可以做得更好!?