Pap*_*ter 7 c++ operator-overloading language-lawyer c++23
c++23operator ()引入了和的静态版本operator []:
#include <iostream>\n#include <format>\n\nstruct S\n{\n static int operator()(int a, int b) { return a + b; }\n static int operator[](int a, int b) { return a - b; }\n};\n\nint main()\n{\n std::print("({})[{}]", S{}(1, 0), S{}[3, 1]); // (1)[2]\n// ^^ ^^ <-- Create temporary instances of \'S\'?!\n std::print("({})[{}]", S()(2, 1), S()[5, 1]); // (3)[4]\n// ^^ ^^ <-- Create temporary instances of \'S\'?!\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n令我震惊的是,为了调用静态版本的运算符()和[]需要类的实例;我期望能够从类型中调用两个运算符(作为其他静态成员),但它的格式不正确:
// type --> v v <-- type\nstd::print("({})[{}]", S(1, 0), S[3, 1]); // (1)[2]\n// static operator() -> \\____/ \\____/ <- static operator[]\nRun Code Online (Sandbox Code Playgroud)\n但S(1, 0)看起来像一个构造函数哈哈,愚蠢的我!,如果类型S碰巧有一个S(int, int)构造函数\xe2\x80\xa6,则会导致歧义,但是那又如何呢?S[3, 1]?这不会与任何类内实体发生冲突。
好吧,也许type(...)和type[...]是有问题的,但是使用作用域运算符怎么样?不幸的是,这也是错误的:
// type --> v v <-- type\nstd::print("({})[{}]", S::(1, 0), S::[3, 1]); // (1)[2]\n// static operator() -> \\____/ \\____/ <- static operator[]\nRun Code Online (Sandbox Code Playgroud)\n我一直在阅读p1169r4和p2589r0论文,但我找不到任何“强制”实例化类型以调用静态运算符的理由(),[]也找不到为什么不允许使用type::(...)or形式。type::[...]
我错过了什么吗?
\nBar*_*rry 13
静态的动机operator(),然后为了一致性,静态的动机operator[]是允许使这些运算符静态。允许s(a, b)不必需要额外的对象参数,而只是希望它能够被优化掉。
但该函数的名称是operator()- 它不是()。S::(a, b)不是今天称呼该接线员的方式,而是S::operator()(a, b). 允许运算符使用这种不同的调用语法是完全不同的功能。
您引用的提案没有理由“强迫”任何东西,因为它们没有强迫任何东西 - 这是现有的语言。
它看起来也不像是一个超级激励功能,因为在您有静态调用或静态下标运算符的情况下,您可能没有状态(否则运算符可能不会是静态的),所以S::(a, b)不是t 任何短于S{}(a, b).
但如果您想以这种方式使用它,您也可以创建一个以下类型的全局对象:
struct S
{
static int operator()(int a, int b) { return a + b; }
static int operator[](int a, int b) { return a - b; }
};
inline S S;
Run Code Online (Sandbox Code Playgroud)
这允许您使用最初想要的语法:
std::print("({})[{}]", S(1, 0), S[3, 1]); // (1)[2]
// static operator() -> \____/ \____/ <- static operator[]
Run Code Online (Sandbox Code Playgroud)