为什么v = 42
不在这里编译?似乎编译器试图调用Foo
的复制赋值运算符,为什么?我怎样才能编译它?
#include <boost/variant.hpp>
struct Foo {
Foo(Foo&&) { }
};
int main() {
boost::variant<int, Foo> v;
v = 42;
}
错误消息是:
In file included from prog.cc:1:
In file included from /usr/local/boost-1.62.0/include/boost/variant.hpp:17:
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:619:21: error: object of type 'Foo' cannot be assigned because its copy assignment operator is implicitly deleted
lhs_content = ::boost::detail::variant::move(*static_cast<T* >(rhs_storage_));
^
/usr/local/boost-1.62.0/include/boost/variant/detail/visitation_impl.hpp:112:20: note: in instantiation of function template specialization 'boost::detail::variant::move_storage::internal_visit<Foo>' requested here
return visitor.internal_visit(
^
/usr/local/boost-1.62.0/include/boost/variant/detail/visitation_impl.hpp:154:13: note: in instantiation of function template specialization 'boost::detail::variant::visitation_impl_invoke_impl<boost::detail::variant::move_storage, void *, Foo>' requested here
return (visitation_impl_invoke_impl)(
^
/usr/local/boost-1.62.0/include/boost/variant/detail/visitation_impl.hpp:240:11: note: in instantiation of function template specialization 'boost::detail::variant::visitation_impl_invoke<boost::detail::variant::move_storage, void *, Foo, boost::variant<int, Foo>::has_fallback_type_>' requested here
, BOOST_VARIANT_AUX_APPLY_VISITOR_STEP_CASE
^
/usr/local/boost-1.62.0/include/boost/preprocessor/repetition/repeat.hpp:29:26: note: expanded from macro 'BOOST_PP_REPEAT'
# define BOOST_PP_REPEAT BOOST_PP_CAT(BOOST_PP_REPEAT_, BOOST_PP_AUTO_REC(BOOST_PP_REPEAT_P, 4))
^
/usr/local/boost-1.62.0/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT'
# define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
^
/usr/local/boost-1.62.0/include/boost/preprocessor/cat.hpp:29:34: note: expanded from macro 'BOOST_PP_CAT_I'
# define BOOST_PP_CAT_I(a, b) a ## b
^
<scratch space>:128:1: note: expanded from here
BOOST_PP_REPEAT_1
^
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:2384:33: note: in instantiation of function template specialization 'boost::detail::variant::visitation_impl<mpl_::int_<0>, boost::detail::variant::visitation_impl_step<boost::mpl::l_iter<boost::mpl::l_item<mpl_::long_<2>, int, boost::mpl::l_item<mpl_::long_<1>, Foo, boost::mpl::l_end> > >, boost::mpl::l_iter<boost::mpl::l_end> >, boost::detail::variant::move_storage, void *, boost::variant<int, Foo>::has_fallback_type_>' requested here
return detail::variant::visitation_impl(
^
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:2398:16: note: in instantiation of function template specialization 'boost::variant<int, Foo>::internal_apply_visitor_impl<boost::detail::variant::move_storage, void *>' requested here
return internal_apply_visitor_impl(
^
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:2125:19: note: in instantiation of function template specialization 'boost::variant<int, Foo>::internal_apply_visitor<boost::detail::variant::move_storage>' requested here
this->internal_apply_visitor(visitor);
^
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:2171:13: note: in instantiation of member function 'boost::variant<int, Foo>::variant_assign' requested here
variant_assign( detail::variant::move(temp) );
^
/usr/local/boost-1.62.0/include/boost/variant/variant.hpp:2189:9: note: in instantiation of function template specialization 'boost::variant<int, Foo>::move_assign<int>' requested here
move_assign( detail::variant::move(rhs) );
^
prog.cc:9:7: note: in instantiation of function template specialization 'boost::variant<int, Foo>::operator=<int>' requested here
v = 42;
^
prog.cc:4:5: note: copy assignment operator is implicitly deleted because 'Foo' has a user-declared move constructor
Foo(Foo&&) {}
^
答案 0 :(得分:2)
似乎编译器试图调用Foo的复制赋值运算符,为什么?
这只是令人困惑的措辞。移动赋值运算符(您没有)也足够了。
至于为什么需要移动赋值运算符:$(".add").on( "click", function() {
try {
$(this).attr('disabled', true);
var IdToAdd = $(this).closest("p").attr("id");
var myFavStaff = JSON.parse(localStorage.getItem("favStaff"));
if (myFavStaff == null) {
myFavStaff = [];
}
myFavStaff .push(IdToAdd );
localStorage.setItem("favStaff", JSON.stringify(myFavStaff ));
}
catch (e) {
if (e == QUOTA_EXCEEDED_ERR) {
console.log("Error: Local Storage limit exceeded" );
} else {
console.log("Error: Saving to local storage not working" );
}
}
});
的{{1}}是根据另一个boost::variant
的赋值实现的。从operator=
开始构建boost::variant
。然后int
移动分配boost::variant<int, Foo>
。哪个需要考虑它被移动分配v
的可能性,即使这不可能发生。
您可以在编译器的错误消息和variant.hpp
中看到boost::variant<int, Foo>
辅助方法对此负责:
Foo
虽然存在允许跳过临时变体的优化,但只有在变量已经包含variant_assign
时才有可能,而且无论如何都无法在编译时确定,因此它不会被阻止template <typename T>
void move_assign(T&& rhs)
{
// If direct T-to-T move assignment is not possible...
detail::variant::direct_mover<T> direct_move(rhs);
if (this->apply_visitor(direct_move) == false)
{
// ...then convert rhs to variant and assign:
//
// While potentially inefficient, the following construction of a
// variant allows T as any type convertible to one of the bounded
// types without excessive code redundancy.
//
variant temp( detail::variant::move(rhs) );
variant_assign( detail::variant::move(temp) );
}
}
的实例化。
答案 1 :(得分:1)
来自the docs:
每个有界类型都必须满足MoveAssignable概念的要求。
MoveAssignable需要移动分配(尽管在我可以找到的文档中的任何地方都没有详细说明)。 Foo
不能移动 - 可分配,因为用户提供的移动构造函数会隐式删除移动赋值运算符。因此,您不能满足此运营商的要求。
这似乎是一个QoI问题。 operator=(int )
没有理由要求Foo::operator=(Foo )
。我们可以在编译时确定哪种类型将是新的参与类型(另一个要求),这是我们需要实例化operator=
的唯一类型。如果变体最初为Foo
,我们只想销毁原始Foo
并构建新的int
。
答案 2 :(得分:0)
我认为编译器警告的这一行告诉我们:
prog.cc:4:5: note: copy assignment operator is implicitly deleted because 'Foo' has a user-declared move constructor
如果没有声明任何类型的用户声明的构造函数,编译器将只生成隐式声明的构造函数
此处的完整说明on Default Constructors
当然可以告诉它生成此默认作业,但不清楚您的实际代码是否正常。具体来说,不清楚为什么你有自定义移动构造函数。
#include <boost/variant.hpp>
struct Foo {
Foo(Foo&&) { }
Foo& operator=(const Foo&) = default;
};
int main() {
boost::variant<int, Foo> v;
v = 42;
}