【发布时间】:2015-06-23 15:24:00
【问题描述】:
我有一个类,只有当类的类型参数不能分别复制/移动构造时,我才想在其中启用复制/移动赋值运算符。所以我试试这个:
#include <type_traits>
template<typename T>
struct Foobar {
Foobar(T value) : x(value) {}
Foobar(const Foobar &other) : x(other.x) {}
Foobar(Foobar &&other) : x(std::move(other.x)) {}
template<bool Condition = std::is_nothrow_copy_constructible<T>::value,
typename = typename std::enable_if<Condition>::type>
Foobar &operator=(const Foobar &rhs) {
x = rhs.x;
return *this;
}
template<bool Condition = std::is_nothrow_move_constructible<T>::value,
typename = typename std::enable_if<Condition>::type>
Foobar &operator=(Foobar &&rhs) {
x = std::move(rhs.x);
return *this;
}
T x;
};
int main() {
Foobar<int> foo(10);
Foobar<int> bar(20);
foo = bar;
foo.operator=(bar);
return 0;
}
现在,Clang 给了我以下错误:
enable_if_test.cpp:31:9: error: object of type 'Foobar<int>' cannot be assigned because its copy assignment operator is implicitly
deleted
foo = bar;
^
enable_if_test.cpp:8:5: note: copy assignment operator is implicitly deleted because 'Foobar<int>' has a user-declared move
constructor
Foobar(Foobar &&other) : x(std::move(other.x)) {}
^
enable_if_test.cpp:32:9: error: call to deleted member function 'operator='
foo.operator=(bar);
~~~~^~~~~~~~~
enable_if_test.cpp:4:8: note: candidate function (the implicit copy assignment operator) has been implicitly deleted
struct Foobar {
^
enable_if_test.cpp:12:13: note: candidate function [with Condition = true, $1 = void]
Foobar &operator=(const Foobar &rhs) {
^
enable_if_test.cpp:19:13: note: candidate function [with Condition = true, $1 = void] not viable: no known conversion from
'Foobar<int>' to 'Foobar<int> &&' for 1st argument
Foobar &operator=(Foobar &&rhs) {
^
2 errors generated.
现在,我包含了对赋值运算符的显式调用,以展示错误的怪异之处。它只是说我的模板是一个候选函数,并没有说明为什么不选择它。
我的猜测是,由于我定义了移动构造函数,编译器隐式删除了复制赋值运算符。由于它被隐式删除,它甚至不想实例化任何模板。但是,我不知道它为什么会这样。
我怎样才能实现这种行为?
(注意:实际代码有合理的理由来定义每个成员,我知道它在这里没有用。)
【问题讨论】:
-
T 不在赋值运算符的直接上下文中,因此不会发生 SFINAE。如果您添加一个默认为 T 的虚拟模板参数,然后用该参数替换 T 来替代您的模板参数的其余部分,它应该可以工作。
-
@0x499602D2 我不能完全理解你的论点。据我所知,OP 中的问题是函数模板不被视为特殊成员函数(默认 ctor 除外)。
-
“它甚至不想实例化任何模板” 据我所知,你最终会得到一个已删除的
operator=(Foo const&)和一个函数模板特化 @987654324 @。作为最后的手段,非模板函数优先于函数模板特化——这会选择已删除的运算符。
标签: c++ templates c++11 assignment-operator