提问人:Zebrafish 提问时间:7/6/2023 更新时间:7/6/2023 访问量:100
为什么编译器找不到赋值运算符?
Why can't the compiler find the assignment operator?
问:
template <typename T>
class MyPointer
{public:
template <typename U>
void operator=(MyPointer<U>&& other)
{
}
char* get() const { return pointer; }
private:
char* pointer;
};
int main()
{
struct B {};
struct D : B{};
MyPointer<B> my_pointer_b;
MyPointer<D> my_pointer_d;
my_pointer_b = my_pointer_d;
}
我得到的错误:
binary '=':未找到采用类型为右操作数的运算符 'MyPointermain::D'(或者没有可接受的转换)
编译器实例化了我使用的特定类型的赋值运算符,因此即使它删除了默认的赋值运算符,实例化的赋值运算符也应该在那里。
答:
5赞
Nelfeal
7/6/2023
#1
template <typename U>
void operator=(MyPointer<U>&& other)
在此,不是转发参考。它是对某些 的右值引用,其中是从参数中推导出来的。MyPointer<U>&&
MyPointer<U>
U
因此,不能使用 lvalue 调用此函数。
如果要使用转发引用,但将其限制为实例,则可以执行如下操作:MyPointer
// forward declaration
template <typename T>
class MyPointer;
template <typename T>
struct IsMyPointerInstance : std::false_type {};
template <typename T>
struct IsMyPointerInstance<MyPointer<T>> : std::true_type {};
template <typename T>
concept MyPointerInstance = IsMyPointerInstance<std::remove_cvref_t<T>>::value;
template <typename T>
class MyPointer {
public:
template <typename U> requires MyPointerInstance<U>
void operator=(U&& other) {
// ...
}
(如果不能使用概念,请使用 SFINAE)
6赞
463035818_is_not_an_ai
7/6/2023
#2
也许 gcc 的错误有助于更清楚地说明这一点:
<source>:24:20: error: cannot bind rvalue reference of type 'MyPointer<main()::D>&&' to lvalue of type 'MyPointer<main()::D>'
24 | my_pointer_b = my_pointer_d;
| ^~~~~~~~~~~~
您不是转发参考。它是一个右值引用。MyPointer<U>&&
来自 cppreference:
转发引用是一种特殊类型的引用,它保留了函数参数的值类别,从而可以通过 转发它。转发引用是:
std::forward
- 函数模板的函数参数,声明为右值引用,引用同一函数模板的 CV-Unqualified 类型模板参数:
- [...自动&&...]
这是一个转发参考
template <typename T> void foo(T&&);
这个不是
template <typename T> void bar(X<T>&&);
评论
U&&
将是通用参考,不是。C<U>&&