void(),逗号运算符(operator)和不可能的(?)重载 [英] The void(), the comma operator (operator,) and the impossible (?) overloading

查看:121
本文介绍了void(),逗号运算符(operator)和不可能的(?)重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下结构:

struct S {};

在C ++ 14中,以下定义有效:

In C++14, the definition below is valid:

constexpr auto f() { return S{}, 'c'; }

以及以下内容之一:

constexpr auto f() { return S{}, void(); }

现在,请考虑以下涉及两个定义中第一个的工作片段:

Now, consider the following, working snippet that involves the first of the two definitions:

#include<type_traits>

struct S {};

constexpr int operator,(S, char) { return 42; }
constexpr auto f() { return S{}, 'c'; }

int main() {
    constexpr int i{f()};
    static_assert(i == 42, "!");
    static_assert(std::is_same<decltype(f()), int>::value, "!");
}

从技术上讲,逗号运算符的重载拦截S{}, 'c',并返回一个整数,如在main函数中正确验证的那样.

Speaking not so technically, the overload of the comma operator intercepts the couple S{}, 'c' and returns an integer, as correctly verified in the main function.

现在,假设我想对f的第二个定义执行相同的操作:

Now, suppose I want to do the same with the second definition of f:

constexpr auto f() { return S{}, void(); }

在这种情况下,逗号运算符应 intercept 形式为S{}, void().
以下定义都不起作用(出于明显的原因):

In this case, the comma operator should intercept the form S{}, void().
Neither the following definition works (for obvious reasons):

constexpr int operator,(S, void) { return 42; }

以下一个(在上一案例中也可以使用):

Nor the one below (that would have worked in the previous case):

template<typename T> constexpr int operator,(S, T &&) { return 42; }

有什么方法可以重载逗号运算符以处理S{}, void()吗?
否则不是不是该标准的不足之处,因为它允许以这种方式使用逗号运算符,但不会给您提供重载同一运算符的机会(即使

Is there any way to overload the comma operator so as to deal with S{}, void()?
Isn't it otherwise a lack in the standard, for it allows to use the comma operator that way, but doesn't give you the chance to overload the same operator (even if the standard mentions that overloaded functions involving S are allowed)?

注意:这个问题是出于好奇而提出的.请避免使用请勿这样做这不是好习惯之类的注释.我不打算在生产环境中这样做.谢谢.

Note: this question is made for the sake of curiosity. Please, avoid comments like do not do that or it is not good practice. I'm not planning to do that in production environments. Thank you.

推荐答案

与此相关的子句是N4140中的13.3.1.2/9 [over.match.oper]:

The relevant clause for this is 13.3.1.2/9 [over.match.oper] in N4140:

如果运算符是运算符,,一元运算符&或运算符->,并且没有可行的功能, 则假定该运算符为内置运算符,并根据第5章进行解释.

If the operator is the operator ,, the unary operator &, or the operator ->, and there are no viable functions, then the operator is assumed to be the built-in operator and interpreted according to Clause 5.

由于void()从来都不是有效的函数参数(请参阅5.2.2/7 [expr.call]),因此永远没有可行的函数,因此将使用内置的,.

As void() is never a valid function argument (see 5.2.2/7 [expr.call]), there never is a viable function and thus the built-in , will be used.

所以不,您尝试做的事情是不可能的.

So no, what you are trying to do is not possible.

实际上,编写这样的迭代器循环

In fact, writing an iterator loop like this

for(...; ++it1, (void)++it2)

是一种标准方法,可通过强制使用内置运算符,来防止用户通过重载其迭代器类型的,来破坏您的代码. (请注意,我并不是说您需要在日常代码中执行此操作.这在很大程度上取决于其实际使用.这是偏执狂的标准库级别.)

is a standard way to prevent users from breaking your code by overloading , for their iterator types by enforcing the built-in operator , to be used. (Note that I am not saying you need to do this in your everyday code. It very much depends on its actual use. This is standard library level of paranoid.)

关于您链接的标准条款:

Regarding the standard clause you linked:

为每种类型预定义的运算符=,(一元)和&,(逗号)的含义可以通过定义实现这些运算符的运算符功能来针对特定的类和枚举类型进行更改. >.

The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators.

但是不能定义这样的函数,因为如上所述,void()从来都不是有效的函数参数.

But such a function cannot be defined because, as I said above, void() is never a valid function argument.

现在,这是否是标准中的监督/问题尚有待商

Now whether or not this is an oversight/problem in the standard is open to debate.

这篇关于void(),逗号运算符(operator)和不可能的(?)重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆