如果对象被用作左值或右值,如何检测和处理
How detect and handle if object is used as l-value or as r-value?
我有一个叫做Properties
的容器类。我想添加operator[](const std::string & name)
,它将返回具有指定名称的属性。
现在让我们考虑没有指定名称的属性。在这种情况下,我不想添加新的具有指定名称的Property
到我的Properties
,如果它被用作l值,否则抛出异常。
Properties pts;
pts.add("name1", val1);
pts.add("name2", val2);
pts["name1"] = val3; //OK
pts["name3"] = val1; //OK creating new Property with value = val1
cout << pts["name4"]; //Ooops can't find Property with name = "name4", so throwing an exception
这在c++中可能吗?我怎么写这样的operator[]
呢?
您可以涵盖您给出的情况,但不是通过实际检查左值到右值的转换是否发生。我认为直接拦截它是不可能的,所以你需要激发一个不同的转换:
-
operator[]
返回代理对象,如John Zwinck所说。 -
代理对象有一个
operator=(const V&)
,因此通过创建密钥来处理分配。可选地,你也可以有operator+=
,operator++
和其余的-我不确定你是否意味着任何左值使用是OK的,或者只是直接赋值。 -
代理对象转换为
V&
,如果密钥不存在则抛出。
编辑:这似乎是模糊的工作,虽然有用例它不涵盖,如传递operator[]
的返回值到一个函数,需要V&
和分配给它在那里。此外,隐藏代理+转换永远不会产生与原始类型完全相同的接口,因为隐式转换最多可能涉及一个用户定义的转换,并且代理会"耗尽"该转换。
#include <iostream>
#include <map>
#include <string>
#include <stdexcept>
struct FunnyMap;
struct ProxyValue {
FunnyMap *ptr;
std::string key;
ProxyValue(const std::string &key, FunnyMap *ptr) : ptr(ptr), key(key) {}
operator int&();
int &operator=(int i);
};
struct FunnyMap {
std::map<std::string, int> values;
ProxyValue operator[](const std::string &key) {
return ProxyValue(key, this);
}
};
ProxyValue::operator int&() {
if (ptr->values.count(key) != 0) {
return ptr->values[key];
} else {
throw std::runtime_error("no key");
}
}
int &ProxyValue::operator=(int i) {
return ptr->values[key] = i;
}
void foo(int &i) {
i = 4;
}
int main() {
try {
FunnyMap f;
f["foo"] = 1;
std::cout << f["foo"] << "n";
std::cout << f["bar"];
// foo(f["bar"]); // also throws
} catch (const std::exception &e) {
std::cout << "Exception: " << e.what() << "n";
}
}
输出:1
Exception: no key
您可以让operator[]
返回一个代理对象,而不是对包含值的普通引用。然后你可以在代理中设置一个标志,当它被分配时(即当代理的操作符=被调用时)。然后,如果从未分配过代理的析构函数,则可以抛出它。当然,你需要用一个布尔值来实例化代理,告诉它是否需要赋值(没有值存在)或不需要赋值(已经设置了值)。
std::uncaught_exception()
检测这种情况。
最后我将引用这篇关于uncaught_exception()
的文章:http://www.gotw.ca/gotw/047.htm
有两个参数反对使用这个函数。首先,当抛出实际上是安全的时,它有时可能返回true。我声称我们可以接受你的情况,因为我们正在努力提供安全检查,如果我们有时不能提供安全检查,那么我们的情况也不会比以前差多少。如果我们同意有时不做检查在你的情况下是可以的,那么文章中的第二个参数("道德"的一个)也可以忽略(因为你的代理不会有两个不同的错误处理机制,它会有一个通常是有效的,但并不总是)。
- 使用CMake检测支持的C++标准
- 当套接字连接断开时检测C/C++Unix
- C/C++预处理器是否可以检测一些编译器选项
- WMI检测进程创建事件-c++
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 下面是我为检测链接列表中的循环而制作的代码
- 落砂模拟碰撞检测C++和SFML
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么C++编译器没有检测到正确声明的类?
- 检测win32服务创建和删除的最佳方法
- 正在LLVM中检测整数比较条件
- 如何在鼠标挂钩过程中检测拖动
- 位移操作和位掩码未检测到重复字符
- 检测 COFF 对象文件中C++内联符号
- qmake:检测目标位宽(32 位或 64 位)
- 增强精神解析器规则以检测语句中的特殊结尾
- 用于C++的静态二进制检测或二进制重写工具和框架
- Tensorflow对象检测在Python和C++(OpenCV)之间有不同的结果
- C++中的张量流对象检测
- 边缘检测-检测错误