编译器在不需要时关心复制构造函数
compiler cares about copy constructor when it doesn't need one
为什么编译器在不需要复制构造函数时关心它?
#include <iostream>
template<typename T>
void print(T);
class Foo {
Foo(const Foo&);
public:
Foo(){}
};
template<>
void print(const Foo& f) {
std::cout << "Foo\n";
}
int main(){
Foo foo;
print(foo);
}
函数 print
被重载以接受 const Foo&
但编译器产生以下编译错误:
main.cpp: In function ‘int main()’:
main.cpp:21:14: error: ‘Foo::Foo(const Foo&)’ is private within this context
21 | print(foo);
| ^
main.cpp:7:5: note: declared private here
7 | Foo(const Foo&);
| ^~~
main.cpp:4:12: note: initializing argument 1 of ‘void print(T) [with T = Foo]’
4 | void print(T);
| ^
为什么会这样?显然我们不需要复制构造函数,因为我们通过引用传递 foo
并且为此我们有 print
的重载。
显式专业化
template<>
void print(const Foo& f) {
std::cout << "Foo\n";
}
需要申请资格转换。
因此将使用主模板而不是对象的特化
Foo foo;
您可以明确指定专业
print<const Foo &>(foo);
您的专业化未用于重载解析。重载解析仅从 primary 模板合成签名。特化仅在调用函数时使用,并且仅当签名与编译器自身合成的签名匹配时使用。由于primary按值接受参数,因此这是参与重载决议的签名:
void print(Foo); // T = Foo
并且它与您在专业化 (T = Foo const&
) 中提供的签名不匹配,因此不会调用专业化。事实上,按原样调用您的专业化的唯一方法是显式指定模板参数:
print<Foo const&>(foo);
前进的方式不是专业化,而是超载。您只需删除 template<>
介绍人即可完成此操作。常规重载参与重载决策,将优先于模板生成的重载。
为什么编译器在不需要复制构造函数时关心它?
#include <iostream>
template<typename T>
void print(T);
class Foo {
Foo(const Foo&);
public:
Foo(){}
};
template<>
void print(const Foo& f) {
std::cout << "Foo\n";
}
int main(){
Foo foo;
print(foo);
}
函数 print
被重载以接受 const Foo&
但编译器产生以下编译错误:
main.cpp: In function ‘int main()’:
main.cpp:21:14: error: ‘Foo::Foo(const Foo&)’ is private within this context
21 | print(foo);
| ^
main.cpp:7:5: note: declared private here
7 | Foo(const Foo&);
| ^~~
main.cpp:4:12: note: initializing argument 1 of ‘void print(T) [with T = Foo]’
4 | void print(T);
| ^
为什么会这样?显然我们不需要复制构造函数,因为我们通过引用传递 foo
并且为此我们有 print
的重载。
显式专业化
template<>
void print(const Foo& f) {
std::cout << "Foo\n";
}
需要申请资格转换。
因此将使用主模板而不是对象的特化
Foo foo;
您可以明确指定专业
print<const Foo &>(foo);
您的专业化未用于重载解析。重载解析仅从 primary 模板合成签名。特化仅在调用函数时使用,并且仅当签名与编译器自身合成的签名匹配时使用。由于primary按值接受参数,因此这是参与重载决议的签名:
void print(Foo); // T = Foo
并且它与您在专业化 (T = Foo const&
) 中提供的签名不匹配,因此不会调用专业化。事实上,按原样调用您的专业化的唯一方法是显式指定模板参数:
print<Foo const&>(foo);
前进的方式不是专业化,而是超载。您只需删除 template<>
介绍人即可完成此操作。常规重载参与重载决策,将优先于模板生成的重载。