boost::any replacement for the code below
我希望摆脱对我的代码的 boost 依赖。我有以下结构构造。在代码中的另一个位置调用和使用此结构时,使用 boost::any_cast。我知道模板类会做到这一点,但很难编写这个模板。 – C 菜鸟。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
struct Properties {
public: Properties() {} Properties(const std::string &s, const boost::any & p) { name = s; value = p; } template <typename T> std::string name; |
- 该程序使用一个变量: std::vector<Properties*> prop;另一个使用 BOOST 的例子是 boost::any_cast< T >(prop[i]->value);
只是为了好玩,我想我会创建一个极简的任何实现:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
//////////////////////////////////////////
// my_any.hpp #include <memory> #include <stdexcept> struct my_any void swap(my_any& other) { _storage.swap(other._storage); } // todo move semantics template <typename T> T& any_cast(my_any& a) { template <typename T> T const& any_cast(my_any const& a) { |
然后您可以按照您的用例所示的方式使用它:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
struct Properties {
public: Properties(const std::string &s=“”, const my_any& p={}) : name(s), value(p) {} template <typename T> Properties(T n) { value = n; } std::string name; #include <vector> typedef std::vector<Properties> Props; int main() std::cout <<“v.size():” << v.size() <<“\ v[0].value = v; try { std::cout <<“v[0].value.size():” << any_cast<Props>(v[0].value).size() <<“\ |
查看输出 Live On Coliru
- 错误:’virtual my_any::storage_base::~storage_base()’ 声明的虚拟不能在类主体中默认另外,在行上:”Properties(const std::string
boost::any 使用类型擦除来存储任何类型的对象,您可以在运行时为其分配不同类型的值。 any_cast 用于检索存储在 any 对象中的具有正确类型的原始值。例如,您当前的课程允许您这样做
1
2 3 4 5 6 |
Properties p(“int”, 42);
std::cout << boost::any_cast<int>(p.value) << ‘\ ‘; p = Properties(“string”, std::string(“hello”)); std::cout << boost::any_cast<std::string>(p.value) << ‘\ ‘; |
您不能只是将上面的类转换为模板并获得相同的功能。如果这样做,您将只能存储一种类型的值。而且您必须将整个 struct 更改为模板,而不仅仅是构造函数。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
template<typename T>
struct Properties { public: Properties() {} Properties(std::string s, T p) : name(std::move(s)) // should use initialization list instead , value(std::move(p)) // of assignment within the body {} Properties(T n) std::string name; |
但是,我上面发布的代码现在是非法的。
1
2 3 4 5 6 |
Properties<int> p(“int”, 42);
std::cout << p.value << ‘\ ‘; // p = Properties<std::string>(“string”, std::string(“hello”)); // will not compile because Properties<int> and Properties<std::string> are // distinct types |
如果这些限制没问题,那么修改后的定义应该适合你。
- 谢谢回复。但是限制是不行的。该程序使用一个变量: std::vector<Properties*> prop;另一个使用 BOOST 的例子是 boost::any_cast< T >(prop[i]->value);
- @user3204803,那么恐怕您将不得不坚持 boost::any 或自己动手。
- @user3204803 恐怕 Jeffrey 是对的;在这种情况下,自己滚动几乎是唯一的其他选择。值得庆幸的是,boost::any 实现起来相对简单,这里是源代码(如果你摆脱各种编译器变通方法和其他选项,它会变得更短)
来源:https://www.codenong.com/21176190/