- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的代码中有一个案例,我想通过模板调用类定义的二元运算符重载,但第二个参数可能是 void 类型。可以写那个专业吗?
为什么:
所以我有一个现有的宏化/模板包装,它可以帮助我记录函数的返回值。
有点像这样:
#define Return return DebugPlacement({__FILE__,__LINE__}) <<=
其中 DebugPlacement 是一个小点类,它具有 operator <<=
的模板化重载
struct DebugPlacement
{
const char* path; int line;
template <class Arg>
const Arg& operator <<= (const Arg& arg)const
{
std::cerr << "DIAG: " << path << ":" << line << " returns " << arg << std::endl;
return arg;
}
};
我们选择运算符 <<= 是因为它非常晦涩难懂,并且表现得有点像现有的流式运算符,但相反。此外,它的低优先级意味着几乎任何合理的表达式都可以写在 RHS 上。
另一个折衷方案:所有类型通常都很简单,因此使用 rvals 并不是什么大问题。我相信我们最终会在这里看到完美转发的需求,但目前还没有。
它打印值并返回它。而且我可以根据需要插入各种通用专业,-char* 等。不需要额外的括号。效果很好,谢谢提问!
在很多情况下,它用于 API stub :
extern int MyFunction(int (arg1), int (arg2));
int MyFunctionStub(int (arg1), int (arg2))
{
Return MyFunction(int (arg1), int (arg2));
}
而这种 stub 行为反过来又被宏观化了。我知道 - 这是一个诅咒和祝福。不用说,我们的用例并不是那么简单。 stub 也有工作要做,所以不能被消除或模板化掉。 stub 的名称在历史上也固定为公共(public)“C”API。
但如果返回类型为 void,一切都会崩溃!
看起来不错的 c++ 大神认为以下是可以接受的,可能是因为模板包装器需要盲目地转发返回类型:
extern void MyVFunction(int (arg1), int (arg2));
void MyVFunctionStub(int (arg1), int (arg2))
{
return MyVFunction(int (arg1), int (arg2));
}
但是使用宏替换我无法添加我的跟踪。他们不喜欢:
extern void MyVFunction(int (arg1), int (arg2));
void MyVFunctionStub(int (arg1), int (arg2))
{
return DebugPlacement({__FILE__,__LINE__}) <<= MyVFunction(int (arg1), int (arg2));
}
Errors (at the call-site):
error: no viable overloaded '<<='
note: candidate template ignored: substitution failure [with T = void]: cannot form a reference to 'void'
那么,是否有某种形式的词来声明需要右手边但类型为 void 的二元运算符的特化?目前我们仍然生活在 c++11 的土地上。我是要等以后的c++标准,还是标准化大神这次不看好我?
当然,我已经尝试了一些方法:
template <>
auto DebugPlacement::operator <<=(void& t)const -> void&
error: cannot form a reference to 'void'
还有
void operator <<=(void t)const
error: argument may not have 'void' type
最佳答案
I have a case in my code where I want to call a class-defined binary operator overload through a template, but the second argument might be type void. Is it possible to write that specialisation?
您可以使用内置二进制 comma operator 处理 void
返回类型:
In a comma expression
E1, E2
, the expressionE1
is evaluated, its result is discarded (although if it has class type, it won't be destroyed until the end of the containing full expression), and its side effects are completed before evaluation of the expressionE2
begins (note that a user-defined operator, cannot guarantee sequencing) (until C++17).
当其右手操作数为 void
时,逗号运算符的计算结果为 void
。逗号运算符只能为非空操作数重载。当任何操作数为 void
时,仅调用内置逗号运算符,不考虑用户定义的 operator,
。
逗号运算符 precedence是最适合您的任务的最低值。
请注意 comma symbol (,
) has different meanings in different contexts :
The comma in various comma-separated lists, such as function argument lists (
f(a, b, c)
) and initializer listsint a[] = {1, 2, 3}
, is not the comma operator. If the comma operator needs to be used in such contexts, it has to be parenthesized:f(a, (n++, n + b), c)
.
C++11 示例:
#include <iostream>
#include <utility>
struct ReturnValueLogger {
char const* file_;
int const line_;
std::ostream& log_file_line() const {
return std::clog << file_ << ":" << line_ << ' ';
}
ReturnValueLogger(ReturnValueLogger const&) = delete;
~ReturnValueLogger() {
if(file_) // operator, overload is not called for void rhs.
log_file_line() << "Return value is void\n";
}
template<class T>
auto operator,(T&& rhs) -> decltype(std::forward<T>(rhs)) { // Not called for void rhs.
log_file_line() << "Return value is " << rhs << '\n';
file_ = 0;
return std::forward<T>(rhs);
}
};
#define Return return ReturnValueLogger{__FILE__,__LINE__},
int f() { return 1; }
void g() {}
int f2() { Return f(); } // Outputs "Return value is 1".
void g2() { Return g(); } // Outputs "Return value is void".
int main() {
f2();
g2();
}
重载逗号运算符对于类似的宏 Throw
也很有用,可以在抛出位置使用堆栈跟踪、文件和行信息检测异常。
关于c++ - 运算符重载无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73641893/
Or 运算符 对两个表达式进行逻辑“或”运算。 result = expression1 Or expression2 参数 result 任意数值变量。 expression1 任意
Not 运算符 对表达式执行逻辑非运算。 result = Not expression 参数 result 任意数值变量。 expression 任意表达式。 说明 下表显示如何
Is 运算符 比较两个对象引用变量。 result = object1 Is object2 参数 result 任意数值变量。 object1 任意对象名。 object2 任意
\ 运算符 两个数相除并返回以整数形式表示的结果。 result = number1\number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
And 运算符 对两个表达式进行逻辑“与”运算。 result = expression1 And expression2 参数 result 任意数值变量。 expression1
运算符(+) 计算两个数之和。 result = expression1 + expression2 参数 result 任意数值变量。 expression1 任意表达式。 exp
我对此感到困惑snippet : var n1 = 5-"4"; var n2 = 5+"4"; alert(n1); alert(n2); 我知道 n1 是 1。那是因为减号运算符会将字符串“4”转
我想我会得到 12,而不是 7。 w++,那么w就是4,也就是100,而w++, w 将是 8,1000;所以 w++|z++ 将是 100|1000 = 1100 将是 12。 我怎么了? int
Xor 运算符 对两个表达式进行逻辑“异或”运算。 result = expression1 Xor expression2 参数 result 任意数值变量。 expression1
Mod 运算符 两个数值相除并返回其余数。 result = number1 Mod number2 参数 result 任意数值变量。 number1 任意数值表达式。 numbe
Imp 运算符 对两个表达式进行逻辑蕴涵运算。 result = expression1 Imp expression2 参数 result 任意数值变量。 expression1 任
Eqv 运算符 执行两个表达式的逻辑等价运算。 result = expression1 Eqv expression2 参数 result 任意数值变量。 expression1 任
我有一个运算符重载的简单数学 vector 类。我想为我的运算符(operator)获取一些计时结果。我可以通过计时以下代码轻松计时我的 +=、-=、*= 和/=: Vector sum; for(s
我是用户定义比较运算符的新手。我正在读一本书,其中提到了以下示例: struct P { int x, y; bool operator、运算符<等),我们
在 SQL 的维基百科页面上,有一些关于 SQL 中 bool 逻辑的真值表。 [1] 维基百科页面似乎来源于 SQL:2003 标准。 等号运算符 (=) 的真值表与 SQL:2003 草案中的 I
我遇到了一个奇怪的 C++ 运算符。 http://www.terralib.org/html/v410/classoracle_1_1occi_1_1_number.html#a0f2780081f
我正在阅读关于 SO 和 answers 中的一个问题,它被提到为: If no unambiguous matching deallocation function can be found, pr
我偶然发现了这个解决方案,但我无法理解其中到底发生了什么。谁能解释一下! 据我了解,它试图通过计算一半的单元格然后将其加倍来计算 a*b 网格中的单元格数量。但是我无法理解递归调用。 请不要建议其他解
Go的基本类型 布尔类型bool 长度:1字节 取值:布尔类型的取值只能是true或者false,不能用数字来表示 整型 通用整型 int / uint(有符号 / 无符号,下面也类似) 长度:根据运
在本教程中,您将学习JavaScript中可用的不同运算符,以及在示例的帮助下如何使用它们。 什么是运算符? 在JavaScript中,运算符是一种特殊符号,用于对运算数(值和变量)执行操作。例如,
我是一名优秀的程序员,十分优秀!