考虑一个X
具有N
成员变量的类,每个变量都有一些可复制和可移动的类型,以及N
相应的 setter 函数。在 C++98 中, 的定义X
可能如下所示:
class X
{
public:
void set_a(A const& a) { _a = a; }
void set_b(B const& b) { _b = b; }
...
private:
A _a;
B _b;
...
};
上述类的 Setter 函数X
可以绑定到左值和右值参数。根据实际参数,这可能会导致创建临时文件并最终导致复制分配;因此,此设计不支持不可复制的类型。
在 C++11 中,我们拥有移动语义、完美转发和通用引用(Scott Meyers 的术语),通过以下方式重写 setter 函数,可以更高效、更通用地使用它们:
class X
{
public:
template<typename T>
void set_a(T&& a) { _a = std::forward<T>(a); }
template<typename T>
void set_b(T&& b) { _b = std::forward<T>(b); }
...
private:
A _a;
B _b;
...
};
通用引用可以绑定到const
/non- const
、volatile
/non-volatile
和任何一般的可转换类型,避免创建临时变量并将值直接传递给operator =
. 现在支持不可复制、可移动的类型。可以通过static_assert
或 通过消除可能不需要的绑定std::enable_if
。
所以我的问题是:作为设计指南,C++11 中的所有(比如说,大多数)setter 函数都应该写成接受通用引用的函数模板吗?
除了更繁琐的语法和在那些 setter 函数中编写代码时无法使用类似 Intellisense 的帮助工具之外,假设原则“将 setter 函数编写为函数模板,尽可能接受通用引用”是否有任何相关的缺点?