【发布时间】:2017-01-23 16:41:49
【问题描述】:
考虑以下结构:
struct S {};
在 C++14 中,下面的定义是有效的:
constexpr auto f() { return S{}, 'c'; }
还有下面这个:
constexpr auto f() { return S{}, void(); }
现在,考虑以下涉及两个定义中的第一个的有效 sn-p:
#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 函数中正确验证的那样。
现在,假设我想对f 的第二个定义做同样的事情:
constexpr auto f() { return S{}, void(); }
在这种情况下,逗号操作符应该截取S{}, void()的形式。
以下定义都不起作用(原因很明显):
constexpr int operator,(S, void) { return 42; }
下面的也不是(在前一种情况下会起作用):
template<typename T> constexpr int operator,(S, T &&) { return 42; }
有没有什么办法可以重载逗号操作符来处理S{}, void()?
否则不是标准中的缺失吗,因为它允许以这种方式使用逗号运算符,但不会让您有机会重载相同的运算符(即使the standard mentions that overloaded functions involving S are allowed)?
注意:这个问题是出于好奇而提出的。请避免像 不要那样做或 这不是好的做法这样的 cmets。我不打算在生产环境中这样做。谢谢。
【问题讨论】:
-
这太疯狂了 ;)
-
@JesperJuhl 是的,我知道。标准游击队。我正在探索语言中最晦涩的角落。 :-)
-
这真的是不可能的。强制转换为
void是防止人们通过重载迭代器类的逗号运算符来破坏您的循环(如for(...;++it1, ++it2))的标准技巧。 -
@kennytm 哦,好的,我现在明白你的意思了。好吧,无论如何,请注意
1 + void()无效,1, void()是有效的。 -
@skypjack 是的,但是一些运算符在重载时会失去其特殊行为,例如
&&、||不再短路。
标签: c++ operator-overloading language-lawyer void comma-operator