如果赋值运算符设为私有,为什么仍允许此赋值?

Why is this assignment still allowed if the assignment operator is made private?

本文关键字:许此 赋值 为什么 赋值运算符 如果      更新时间:2023-10-16

给定这个例子:

// test.cpp
class A {
public:
private:
A& operator=(const A&);  // don't allow assignment operator
A(const A&);  // don't allow default copy constructor
void func();
};
template<class T>
class B {
public:
B(A &a) : a_(a) {}
void setA(A* a) { a_ = *a; }  // No error is raised here.
void func();
protected:
B& operator=(const B&) { return *this; }
A& a_;
};
我希望在 B 中大约void setA(A* a) { a_ = *a; }

时引发错误,因为 A 的赋值运算符是私有的,A 和 B 不是朋友,但是当我编译它时不会引发错误。

$ g++ -c test.cpp  // My invocation for reference

我的问题是为什么允许这样做?根据 c++ 标准,这种行为是否可能得到保证?

我注意到,如果我没有将 B 作为模板化类,我会按预期收到错误。

$ g++ -c test.cpp
test.cpp: In member function ‘void B::setA(A*)’:
test.cpp:11:29: error: ‘A& A::operator=(const A&)’ is private within this context
void setA(A* a) { a_ = *a; }
^
test.cpp:4:8: note: declared private here
A& operator=(const A&);  // don't allow assignment operator
^~~~~~~~

这让我相信,因为我实际上并没有"使用"模板化的B,编译器可以简单地"忽略它"并优化它。我觉得这很难相信,因为我没有使用优化进行编译,而且当我使用模板化 B 时我仍然无法重现错误。

// Appending this to test.cpp still doesn't result in an error.
void func(A &alloc) {
B<int> b(alloc);
b.func();
}

我还可以确认,对于正常方法,我得到了预期的错误。将 B 中的void func();更改为void func() { a_.func(); }会导致:

test.cpp:14:22: error: 'func' is a private member of 'A'
void func() { a_.func(); }
^
test.cpp:6:10: note: declared private here
void func();
^

我已经用 clang++ (v6.0.1)、g++ (v7.4.0) 和树尖确认了所有这些行为,反对-std=c++98-std=c++17.

类模板的非虚拟成员函数(如示例中的setA)不会实例化,除非实际使用。

我的问题是为什么允许这样做?

其实不然。

但是,由于您从未实际实例化模板B<T>::setA(),因此代码尚未"完成编译"。

我发现这很难相信,因为我没有使用优化进行编译

这与优化无关。

当我使用模板化 B 时,我仍然无法重现错误。

您需要致电setA()


您可能会认为这是替换失败不是错误的扩展;我将称之为不使用损坏的模板的事情不是错误。或简称NUTBTTINAE。:)


另请参阅:为某些不可复制或可移动的T实例化std::vector<T>,并观察它是否有效,直到您尝试将内容推入其中。