比较 boost::任何内容
我正在使用一个容器来保存指向任何内容的指针列表:
struct Example {
std::vector<boost::any> elements;
}
为了在此容器中插入元素,我编写了几个辅助函数(struct Example
的成员):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
现在,我想仅当元素不存在于该容器中时才插入元素。为此,我认为我只需要使用适当的比较器函数对 elements
调用 search
即可。但是,我不知道如何比较 boost::any
实例。
我的问题: 知道我的 boost::any 实例始终包含指向某些内容的指针;是否可以比较两个 boost::any
值?
更新
感谢您的回答。我还设法以一种可能不安全的方式做到这一点:使用boost::unsafe_any_cast
来获取void**
并比较底层指针。
目前,这一切运行良好。不过,我很感谢您的评论:也许这是一个很大的错误!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if ( any_compare(a,*it) ) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
I am using a container to hold a list of pointers to anything:
struct Example {
std::vector<boost::any> elements;
}
To insert elements in this container, I had written a couple of helper functions (members of the struct Example
):
void add_any(boost::any& a) {
elements.push_back(a);
}
template<typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
Now, I would like to insert elements only when they are not present in this container. To do this, I thought that I would only need to call search
over elements
with an appropriate comparator function. However, I do not know how to compare the boost::any
instances.
My question:
Knowing that my boost::any
instances always contain a pointer to something; is it possible to compare two boost::any
values?
update
I thank you for your answers. I have also managed to do this in a probably unsafe way: using boost::unsafe_any_cast
to obtain a void**
and comparing the underlying pointer.
For the moment, this is working fine. I would, however, appreciate your comments: maybe this is a big mistake!
#include <boost/any.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool any_compare(const boost::any& a1, const boost::any& a2) {
cout << "compare " << *boost::unsafe_any_cast<void*>(&a1)
<< " with: " << *boost::unsafe_any_cast<void*>(&a2);
return (*boost::unsafe_any_cast<void*>(&a1)) ==
(*boost::unsafe_any_cast<void*>(&a2));
}
struct A {};
class Example {
public:
Example() : elements(0),
m_1(3.14),
m_2(42),
m_3("hello"),
m_4() {};
virtual ~Example() {};
void test_insert() {
add_to_list(m_1);
add_to_list(m_2);
add_to_list(m_3);
add_to_list(m_4);
add_to_list(m_1); // should not insert
add_to_list(m_2); // should not insert
add_to_list(m_3); // should not insert
add_to_list(m_4); // should not insert
};
template <typename T>
void add_to_list(T& a) {
boost::any bany = &a;
add_any(bany);
}
private:
vector<boost::any> elements;
double m_1;
int m_2;
string m_3;
A m_4;
void add_any(const boost::any& a) {
cout << "Trying to insert " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
vector<boost::any>::const_iterator it;
for (it = elements.begin();
it != elements.end();
++it) {
if ( any_compare(a,*it) ) {
cout << " : not inserting, already in list" << endl;
return;
}
cout << endl;
}
cout << "Inserting " << (*boost::unsafe_any_cast<void*>(&a)) << endl;
elements.push_back(a);
};
};
int main(int argc, char *argv[]) {
Example ex;
ex.test_insert();
unsigned char c;
ex.add_to_list(c);
ex.add_to_list(c); // should not insert
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我能想到的唯一简单的方法是对存储在
any
实例中的类型进行硬编码支持,从而破坏了any
的大部分实用性。使用C++11 的
type_index
您可以使用一个std::map
或std::unordered_map
键控于std::type_index(some_boost_any_object.type())
- 类似于 Alexandre 中的建议他的评论如下。The only easy way to do this I can think of involves hardcoding support for the types that you're storing in the
any
instances, undermining much of the usefulness ofany
...With C++11's
type_index
you could use astd::map
orstd::unordered_map
keyed onstd::type_index(some_boost_any_object.type())
- similar to what Alexandre suggests in his comment below.如果您可以更改容器中的类型,则有 Boost.TypeErasure。它提供了自定义
any
的简单方法。例如,我使用这样的 typedef 来实现类似的目的:Foo
的行为与boost::any
完全相同,除了它可以比较相等性并使用boost::type_erasure::any_cast
而不是boost::any_cast
。If you can change type in container, there is Boost.TypeErasure. It provides easy way to customize
any
. For example I'm using such typedef for similar purpose:Foo
behaves exactly the same asboost::any
, except that it can be compared for equality and useboost::type_erasure::any_cast
instead ofboost::any_cast
.无需创建新类。尝试使用 xany https://sourceforge.net/projects/extendableany/?source=directory xany 类允许向任何现有功能添加新方法。顺便说一句,文档中有一个示例,它完全符合您的要求(创建可比较的_any)。
There is no need to create new class. Try to use xany https://sourceforge.net/projects/extendableany/?source=directory xany class allows to add new methods to any's existing functionality. By the way there is a example in documentation which does exactly what you want (creates comparable_any).
也许这个算法能派上用场>>
http://signmotion.blogspot.com/2011/12/boostany.html
按类型和内容比较两个任意值。尝试将字符串转换为数字以获得相等。
Maybe this algorithm come in handy >
http://signmotion.blogspot.com/2011/12/boostany.html
Compare two any-values by type and content. Attempt convert string to number for equals.
你不能直接提供它,但你实际上可以使用
any
作为基础类型......尽管对于指针来说它是毫无意义的(啊!)和一个模板化构造函数:
这基本上是
boost: :任何
。现在我们需要用我们的比较机制来“增强”它。
为此,我们将“捕获”std::less 的实现。
并扩充
any
的构造函数。然后,我们提供了
less
(或operator<
)的特化注意:封装等...留给读者作为练习
You cannot directly provide it, but you can actually use
any
as the underlying type... though for pointers it's pointless (ah!)And a templated constructor:
This is, basically,
boost::any
.Now we need to "augment" it with our comparison mechanism.
In order to do so, we'll "capture" the implementation of
std::less
.And augment the constructor of
any
.Then, we provided a specialization of
less
(oroperator<
)Note: encapsulation, etc... are left as an exercise to the reader