C++运算符[]重载,模板访问boost::variant
C++ operator[] overloading with template accessing boost::variant
我有一个带有map属性的类,其值为boost::variant。
typedef boost::variant<char, int, bool, unsigned short, float, timeval, double > MultiType;
class A {
public:
template<class T>
T& operator[](const std::string& key) {
return boost::get<T>(map_[key]);
}
template<class T>
std::string keyTypeToString(const std::string& key) {
std::stringstream ss;
ss << boost::get<T>(map_[key]);
return ss.str();
}
private:
std::map<std::string, MultiType> map_;
};
来自主:
A a;
a["param"];
编译器报告此错误:
/src/main.cpp:8:25:错误:'a["param"]'中的'operator[]'不匹配
../src/main.cpp:8:25:注意:候选者是:
../src/util/A.h:53:5:note:template T&A: :运算符[](常量字符串&(
也许我错过了一些琐碎的事情,但我不明白我错在哪里了。。
从这个开始:
template<class T>
T& get(const std::string& key) {
return boost::get<T>(map_[key]);
}
您将其称为类似于a.get<int>("hello")
,其中它将获得元素"hello"
作为int
。
接下来,写下:
struct pseudo_ref {
std::string const& str;
A* a;
template<typename T>
operator T&()&&{
return a->get<T>(str);
}
template<typename T>
pseudo_ref operator=( T&& t ) && {
a->get<typename std::decay<T>::type>(str) = std::forward<T>(t);
return {str, a};
}
pseudo_ref(pseudo_ref const&)=delete;
pseudo_ref& operator=(pseudo_ref const&)=delete;
pseudo_ref( std::string const& s, A* a_ ):str(s), a(a_) {}
};
然后返回A
:
pseudo_ref operator[](std::string const& str) {
return {str, this};
}
我们得到了[]
,它可以神奇地为您转换,只要您使用完全正确的类型分配给它/从中读取。
这有点危险,但很酷。
如果您想要一个const
pseudo_ref,则需要另一个类来表示它(没有=
和operator T const&
而不是operator T&
(。
在实践中,这种胡言乱语很少值得
我在C++11中写了这篇文章,因为在C++03中写这篇文章会稍微痛苦一些(并且会遇到pseudo_ref
的终身问题——如果你有auto&& x = a["hello"]
,这些问题仍然存在(,减少痛苦是好事。
class A {
public:
class proxy {
friend class A;
private:
MultiType& it;
proxy(MultiType& it): it(it) {}
public:
template<typename T>
operator T&() {
return boost::get<T>(it);
}
};
proxy operator[](const std::string& key) {
return proxy(map_[key]);
}
private:
std::map<std::string, MultiType> map_;
};
解释:
我看得出来亚克也在尝试类似的事情我已经在代理中封装了map_[key]
中的MultiType&
,然后留下了转换(类型转换(运算符的工作。仅此而已。
无需分配的简单a[""]
将为您提供代理。double d = a["double"]
将尝试将proxy
转换为double
,从而调用proxy::operator double&()
(我不得不测试它,因为我不确定类型推导是否能正常工作,或者需要更多的工作-好吧,它能工作!(
下午注意:从提供的问题和代码中不清楚允许哪些操作。我们可以修改proxy
以允许其他操作,或者通过更改类型转换运算符的签名来返回const T&
,使其更像readonly
。
允许修改会导致问题:为什么不直接使用MultiType&
?(从A::operator[]
返回(这就引出了一个问题:为什么是class A
?
AFTERNOTE#2:boost::variant没有类型转换运算符,这一定是有原因的
int i = a["double"]
运行时异常!我认为最好的解决方案是对MultiType进行子类,并在那里定义类型转换运算符(同时检查boost::variant::which(((。
分配给现有名称:
class A { ...
class proxy { ...
template<class T> proxy& operator=(const T& rhs) {
it = rhs; return *this; }
但只有当我们在地图中已经有了一些价值时,以上内容才能发挥作用。
class A { ...
A() { map_["pi"] = 3.14; } ...
a["pi"] = 3.1415;
完成重新设计:
class MultiType: public boost::variant<int, double, ...> {
public:
template<class T> operator T() {
switch(which()) {
case 0: return boost::get<int>(*this);
case 1: return boost::get<double>(*this);
...
现在我们可以直接使用std::map<std::string, MultiType>
(不需要class A
或任何proxy
(。
template<class T>
T& operator[](const std::string& key) {
return boost::get<T>(map_[key]);
}
编译器无法从类似a["param"];
的调用中推断出T
。您需要明确指定
a.operator[]<int>("param");
我怀疑你在追求什么,但我知道什么。
- 如何在使用 Boost MSM 编写的状态机中直接访问任何状态
- 如何在 boost 中访问现有图的子图
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 如何在 boost::msm 中实现可以访问状态机 (SM) 的后端/前端的"BaseState"
- 有没有办法访问C++ Boost rtree 中的非叶节点
- 链接 boost 库时"Error while loading shared libraries"引发的,除了我无法使用 root 访问权限来修复它
- 如何访问boost :: asio :: streamBuf输入作为字符串
- 访问Boost Bind时,共享库中的C 符号查找错误
- 我应该如何访问 Boost SHA1 哈希
- 如何通过索引访问 boost::multi_index::multi_index_container<> 的所有元素?
- 访问boost::multi_index中hashed_unique中的数据
- 如何实例化和访问boost mpl类型
- 访问boost::几何体多边形中的点数据时出错
- 访问boost::graph中std::shared_ptr的成员函数
- C++运算符[]重载,模板访问boost::variant
- 如何访问boost::spirit::karma中嵌套对象的数据
- 访问boost::fusion::tuple中的第0个元素
- 无法使用 boost::bind 来访问 boost::tuple 元素
- 访问Boost MultiArray中元素的最快方法
- 访问boost::ptr_vector中的派生对象