gpt4 book ai didi

c++ - 运算符重载无效

转载 作者:行者123 更新时间:2023-12-05 01:03:44 25 4
gpt4 key购买 nike

我的代码中有一个案例,我想通过模板调用类定义的二元运算符重载,但第二个参数可能是 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 expression E1 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 expression E2 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 lists int 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com