我有很多boost :: any的向量 在这个向量中,我需要对std :: vector和IContainer
类型的元素执行一些操作class IContainer
{
public:
virtual ~IContainer(){}
virtual const boost::any operator[](std::string) const = 0;
};
class AContainer : public IContainer
{
std::vector<int> vect_;
std::string name_;
public:
AContainer() : vect_({0, 1, 2, 3, 4, 5}), name_("AContainer") {}
virtual const boost::any operator[](std::string key) const
{
if (key == "str")
return (name_);
if (key == "vect")
return (vect_);
return nullptr;
}
};
所以我做了以下功能(非常丑陋),但谁工作正常
m是const std::vector<boost::any>&
for (const auto & elem : m)
{
try
{
std::vector<int> v = boost::any_cast<std::vector<int>>(elem);
display(v);
}
catch(boost::bad_any_cast){}
try
{
std::vector<IContainer*> v = boost::any_cast<std::vector<IContainer*>>(elem);
display(v);
}
catch(boost::bad_any_cast){}
try
{
AContainer v(boost::any_cast<AContainer>(elem));
try
{
display(boost::any_cast<const std::vector<int>>(v["vect"]));
}
catch (boost::bad_any_cast){}
try
{
std::cout << boost::any_cast<const std::string>(v["str"]) << std::endl;
}
catch (boost::bad_any_cast){}
try
{
display(boost::any_cast<std::vector<int> >(v));
}
catch (boost::bad_any_cast) {}
}
catch(boost::bad_any_cast){}
}
我试图添加许多“try{}try{}catch{}
”,但它无效
你有什么比我做的更好的解决方案
修改 的
我尝试过James Kanze,user1131467和Praetorian
的解决方案所以这3个工作正常,但是当我计算执行时间时,user1131467的答案比另一个快一点。我现在必须找到一种解决方案,将每种类型存储在地图中以避免所有这些if / else
我还将看一下boost :: variant
答案 0 :(得分:7)
使用any_cast
的指针形式更加清晰,因为它使用了指针的可空性:
for (const auto & elem : m)
if (T1* p = any_cast<T1>(&elem))
{
do stuff with *p;
}
else if (T2* p = any_cast<T2>(&elem))
{
do stuff with *p;
}
else if (...)
{
...
}
这也有利于每个案例进行一次演员。
答案 1 :(得分:5)
您可以创建一个函数:
template <typename T>
bool
isInstanceOf( boost::any const& object )
{
return boost::any_cast<T>( &object ) != nullptr;
}
并使用它,如果要检查:
if ( isInstanceOf<std::vector<int>>( elem ) ) {
display( boost::any_cast<std::vector<int>>( elem ) );
} else if ( isInstanceOf<std::vector<IContainer*>>( elem) ) {
display( boost::any_cast<std::vector<IContainer*>>( elem) );
}
// ...
答案 2 :(得分:2)
您可以在any_cast
周围编写自己的包装器,以吞下异常。
template<typename T>
bool nothrow_any_cast( boost::any& source, T& out )
{
try {
out = boost::any_cast<T>( source );
} catch ( boost::bad_any_cast const& ) {
return false;
}
return true;
}
然后将其用作
std::vector<int> vect;
std::string str;
if( nothrow_any_cast(v["vect"], vect ) ) {
// succeeded
} else if( nothrow_any_cast(v["str"], str ) ) {
// succeeded
} ...
但是,如果你这样做,你默认构建所有类型,然后分配它们;所以,即使它看起来更清洁一点,但它是否比你已经拥有的更好是值得商榷的。
答案 3 :(得分:0)
您可以将所有语句放在一个try块中:
try {
// do all your stuff
}
catch (boost::bad_any_cast) {}
答案 4 :(得分:0)
您在输入catch(...){}
区块时错过了添加任何说明。因此,当抛出异常时,您根本不处理它。
适当的处理通常包括跟踪错误级别并尝试解决错误状态(如果可能)。
因为在每个分支中都会捕获相同的异常,所以可以将它们聚合到一个块中:
try{ ... }
catch(boost::bad_any_cast) { ...}
答案 5 :(得分:0)
为什么不使用boost :: any_cast的指针替代,它不会抛出任何东西,如果请求的类型与商店类型不匹配,则返回nullptr。 如果你得到一个指针,你可以写一个重载显示,这需要任何 指针,检查它是否为null,如果指针不为空,则调用实际的显示函数。
template<typename T>
void display(T* p) { if ( p ) display(*p); }
使用上面的模板,只会调用display来进行正确的演员。
for ( const auto& elem : m ) {
display(boost::any_cast<int>(&elem));
display(boost::any_cast<my_type>(&elem));
....
}
答案 6 :(得分:0)
答案中没有一个是现在标准中的简单方法。
如果使用“ std :: any”,则只需使用“ type()”函数即可获取包含项的typeid。