模板类的特殊成员函数(特别是复制/移动构造函数和复制/移动赋值运算符)何时实例化?一旦类本身被实例化,还是仅在需要它们时?
这出现在以下情况:
template <class T, class U>
struct pair
{
T first;
U second;
pair() : first(), second() {}
pair(const pair&) = default;
};
struct S
{
S() {}
S(const S&) = delete;
S(S&&) = default;
};
int main()
{
pair<int, S> p;
}
Clang 拒绝编译此代码,出现以下错误:
test.cpp:9:5: error: the parameter for this explicitly-defaulted copy constructor is const, but a member or base requires it to be
non-const
pair(const pair&) = default;
^
test.cpp:21:18: note: in instantiation of template class 'pair<int, S>' requested here
pair<int, S> p;
^
建议它在实例化类后立即尝试实例化复制构造函数。
然而,GCC 可以很好地编译代码,这表明它只会在实际需要时尝试实例化复制构造函数。
哪个编译器的行为是正确的?
(赋值运算符也有类似的差异。)
更新:这与pair
此示例中的复制构造函数是default
ed 的事实有关,因为如果我将其定义更改为
pair(const pair& p) : first(p.first), second(p.second) {}
然后代码也会通过clang。