我有以下错误消息:
/usr/include/boost/variant/detail/visitation_impl.hpp:207: typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor &, VPCV, mpl::true_, NBF, W *, S *) [W = mpl_::int_<20>, S = boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_end>, boost::mpl::l_iter<boost::mpl::l_end> >, Visitor = boost::detail::variant::copy_into, VPCV = const void *, NBF = boost::variant<TypeInfo, int, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_>::has_fallback_type_]: Assertion `false' failed.
当我将std::vector<A>
作为参数传递给某个函数并且A
定义为using A = boost::variant<B, int>;
时,就会发生这种情况。
简单来说,B
的定义如下:
class B
{
Data data;
std::vector< boost::variant<std::shared_ptr<C>, B> > vec;
};
错误消息中 B
TypeInfo
。
void func(std::vector<B> vec); //signature
auto result = func(that_vector_with_variants); //that line causes an error
我在https://svn.boost.org/trac/boost/ticket/5146
找到了类似的错误我的问题是:它是助推器中的错误吗?如何使我的代码工作?
更新
我认为我必须补充一点,如果我将std::vector<boost::variant<std::shared_ptr<C>, B> > vec;
更改为std::vector<boost::variant<C*, B> > vec;
,那么一切正常。
答案 0 :(得分:3)
走出困境,从阅读错误报告中,你可能无意中做了这样的事情:
#include <iostream>
#include <boost/make_shared.hpp>
#include <boost/variant.hpp>
using P = boost::shared_ptr<int>;
using V = boost::variant<P, int>;
using C = std::vector<V>;
int main() {
P p = boost::make_shared<int>(42);
assert(p.unique());
C v = { p };
assert(!p.unique());
v = std::move(v);
assert(!p.unique()); // WHOOPS assert fails
}
当然这个样本是设计的,因为我不知道你的实际代码/用例。
最后一个断言失败了。这是因为内部操作的顺序是这样的:在分配新值之前清除原始变体(并且包含的值被破坏):
“永不空”保证
虽然永不空洞的保证起初可能看起来“显而易见”,但事实上如何实现它通常并不简单
比照。来自Boost Variant“设计概述”的The "Ideal" Solution: False Hopes
所以,如果我们没有对int
中的p
进行“引用”,则此操作会在重新分配之前销毁该实例。
在这种情况下,它看起来更像是一种使用模式(基本上使用智能指针¹进行就地修改)以避免。在这种特殊情况下,这些似乎可行(在我的编译器/库实现上):
std::move(v.begin(), v.end(), v.begin());
// or
std::copy(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()), v.begin());
// or
v.assign(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end()));
但我当然更喜欢把它写得更像
C tmp = std::move(v);
v = std::move(tmp);
仅仅因为没有其他保证。
¹总是有危险!即使Scott Meyers在他的“更有效的C ++”中也有这种感觉,请参阅 erratum p.200/202
²相关:What does the standard library guarantee about self move assignment?