对存储在boost::any中的向量调用vector::size()
call vector::size() on vector stored in boost::any
我在boost::any
中存储了值,并且我希望有一个函数,如果boost::any
包含std::vector
,该函数将返回元素数。
以下是使用示例:
int a = 42;
vector<int> v = {1,2,3,4};
vector<int> w;
boost::any aa = a;
boost::any av = v;
boost::any aw = w;
// I would like to have this function `count`
count( aa ) // return 1
count( av ) // return 4
count( aw ) // return 0
// I can do following. But I do not like the template argument.
count<int>( aa ) // return 1
count<int>( av ) // return 4
count<int>( aw ) // return 0
count<float>( aa ) // error
问题是,我不能在不指定T
的情况下简单地转换为vector<T>
。有办法绕过它吗?
解决方案可以使用一个中间容器:
class vector_holder_base {
public:
virtual std::size_t size() = 0;
}
template <class T, class... Others>
class vector_holder : public vector_holder_base {
public:
vector_holder(const std::vector<T, Others...>& val) {...}
vector_holder(std::vector<T, Others...>&& val) {...}
vector_holder& operator=(const std::vector<T, Others...>& val) {...}
vector_holder& operator=(std::vector<T, Others...>&& val) {...}
std::size_t size() override {
return values.size();
}
private:
std::vector<T, Others...> values;
}
那么你所要做的就是:
boost::any aa = vector_holder<int>(a);
std::size_t count = boost::any_cast<vector_holder_base>(aa).size();
正如您所看到的,在检索大小时,您不需要知道矢量模板类型。
然而,您需要考虑向量的多个副本(当您将其传递给vector_holder
时,然后当vector_holder
复制到boost::any
时(考虑移动语义)。
std::vector<int>
和std::vector<float>
在运行时是不相关的类型。
boost::any
类型(确切地说)将复制和提取擦除到自己的类型,不再如此。
如果您想获取不相关的(运行时)类型并类型擦除其他属性,则应该检查boost.TypeErasure
,或者自己进行此类擦除。
或者,增强的any
(具有类型擦除的size
)可以工作。假设C++11支持:
struct sized_any;
typedef std::size_t(sizer_t*)(sized_any const*)>;
template<class ValueType>
struct make_sizer {
sizer_t operator()() const {
return [](sized_any const*){return 1;}
}
};
template<class ValueType, class... Whatever>
struct make_sizer< std::vector<ValueType, Whatever...> > {
sizer_t operator()() const {
return [](sized_any const* n){
// convert n to a const std::vector<ValueType, Whatever...>*
// invoke .size()
}
}
};
struct sized_any : private boost::any {
sized_any( sized_any const& o ) = default;
sized_any( sized_any && o ) = default;
sized_any():boost::any(), size([](sized_any const*){return 0;}) {}
sized_any & operator=(const sized_any &) = default;
sized_any & operator=(sized_any &&) = default;
template<typename ValueType> sized_any(const ValueType &v):boost::any(v), sizer(make_sizer<ValueType>{}())
{}
template<typename ValueType> sized_any(ValueType &&v):boost::any(std::move(v)), sizer(make_sizer<ValueType>{}())
{}
template<typename ValueType> sized_any & operator=(const ValueType & v){
this->boost::any::operator=(v);
sizer=make_sizer<ValueType>{}();
return *this;
}
template<typename ValueType> sized_any & operator=(ValueType && v) {
this->boost::any::operator=(std::move(v));
sizer=make_sizer<ValueType>{}();
return *this;
}
~sized_any() = default;
// modifiers
sized_any & swap(sized_any & o) { this->boost::any::swap(o); std::swap( sizer, o.sizer ); }
std::size_t size() const { return sizer(this); }
private:
sizer_t sizer;
};
boost::any
的私有继承是阻止boost::any::swap
被直接调用或其他可以改变boost::any
中存储的类型的函数。您必须重新实现/转发在boost::any
上操作的函数才能在sized_any
上操作。
基本设计很简单。我们维护了一个boost::any
,每当它的类型发生变化时,我们都会构建一个新的函数指针,可以从中提取合适的大小。sizer会将一个指向sized_any
的指针带到我们的复制/赋值运算符,这是它所需要的所有状态(所以我们不需要在函数指针中存储任何状态)。
以上并不是一个完整的实现,而是一个草图。
额外的状态(函数指针)必须独立维护,所以any
的无状态修改是不可能的。
- 循环中的条件:为什么每次都调用strlen(),而vector.size()只调用一次
- 如果 std::vector::clear() 不是静态的,如何在没有实例的情况下调用它?
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 从返回 std::optional of std::vector 的函数中获取结果到调用方
- 在 C++20 之前,在带有常量或引用字段的"A"上调用 'std::vector<A>
- 为什么我的向量::擦除调用会抛出"vector subscript out of range"?
- 错误:调用"es_queue::set_rpc_vector(std::vector >&, std::__cxx11::string)"没有匹配函数
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 对于优化级别为 0 的 std::vector,析构函数被调用两次
- push_back std::vector,则重复调用复制构造函数
- 双重调用传递给 std::vector::emplace_back 的类的复制构造函数
- 如何在Visual C++中为 std::vector 调用_Verify_range?
- std::vector 范围构造函数可以调用显式转换吗?
- 在循环条件中调用const vector size()似乎缺少优化
- 在抛出"std::out_of_range"的实例后调用的 C++ 终止 std::vector
- C++如果调用 vector,矢量分割错误会导致崩溃
- std::vector 调用在重新分配时无论如何都包含对象的析构函数?
- 我可以用std::vector调用接受数组/指针参数的函数吗
- 从 std::vector c++ 调用 std::function 时崩溃
- 如何调用c++函数从c#中获取Vector调用