为什么需要带有 const 引用参数的重复代码
Why duplicate code is needed with const reference arguments?
在这次采访中,Stepanov 展示了如何在C++中实现泛型max
函数。
尝试以面向对象的方式实现一个简单的事情,比如max。 我不知道该怎么做。使用泛型编程我可以 写:
template <class StrictWeakOrdered> inline StrictWeakOrdered& max(StrictWeakOrdered& x, StrictWeakOrdered& y) { return x < y ? y : x; } and template <class StrictWeakOrdered> inline const StrictWeakOrdered& max(const StrictWeakOrdered& x, const StrictWeakOrdered& y) { return x < y ? y : x; }
(你确实需要 & 和 const &)。
为什么需要编写两次代码?这是否有助于编译器进行优化或约定以减少错误?max
const
版本的主体相同的特殊情况吗?
一个 N 个参数的函数应该有多少个有效的const
和非const
排列来定义一个完整的 API?
首先,您需要非const
版本来允许类似
max(a, b) = something;
如果您不想做这些事情,您可以只提供 const
版本以涵盖所有情况。这基本上就是标准std::max
所做的。
您也不需要提供更多const
和非const
的排列,仅当所有输入都是非const
时才返回非const&
才有意义,所有其他情况都由const
版本正确处理。
如果要避免代码重复,可以执行以下操作:
template <class StrictWeakOrdered>
inline StrictWeakOrdered& max(StrictWeakOrdered& x, StrictWeakOrdered& y) {
const auto &xr = x;
const auto &yr = y;
return const_cast<StrictWeakOrdered&>(max(xr, yr));
}
在这种特殊情况下,const_cast
是安全的,因为您已经知道输入实际上是非const
。现在,您只需提供const
情况的实现。
因此,提供两次实现不是必需的,也不应该帮助编译器,但上述内容是否比 Stepanov 所做的更具可读性是值得商榷的。
您实际上不需要这两个版本。你可以这样写。
template <class S, class T>
decltype(auto) max(S&& a, T&& b) {
using Ret = std::conditional_t<
std::is_const<std::remove_reference_t<S>>::value, S, T>;
if (b < a)
return std::forward<Ret>(a);
return std::forward<Ret>(b);
}
如果const
任何一个参数,则回退到const
.
如果您不打算修改参数,则可以使用const&
版本。所有内容都应绑定到常量引用。
C++11 还引入了引用折叠,模板参数T&&
有时称为通用引用。在这种情况下,当实例化例如int&
的参数类型时,我们将int& &&
哪个折叠为int&
。现在,您可以将函数编写为
template <class T1, class T2>
inline T1 const& max(T1&& x, T2&& y) {
T1 const& x_=x;
T2 const& y_=y;
return (x_ < y_) ? (y_) : (x_);
}
这可以使用常量值、临时值(r 值)和可变变量来调用:
int const a=1;
int b=2;
max(b,b) = 23;
std::cout << max(a,a) << max( int{4}, int{5} ) << b << max(int{4}, a);
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 根据编译时参数在 C 中重复代码
- 扩展C++生成的代码的模板参数类型名称
- 将函数作为参数传递以避免重复代码
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++基于输入参数的动态代码生成
- 调用参数不是原子参数的函数是此代码引发异常的原因吗?
- 引入参数化构造函数后显示 LNK 2019 未解析外部符号的代码错误
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- C++17.处理使用 auto 相关的模板参数.代码排序困难
- 为什么EclipseCDT代码格式化程序有时会在模板参数中引入空格
- 我写了一个类,它总是将其函数参数委托给它的成员,我该如何改进代码
- 编译器是否C++具有相同模板参数集的每个模板类实例生成代码?
- 如何将char数组声明为函数参数?或告诉我此代码中还有其他问题?
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 如何基于构造函数参数模板化类成员函数的代码
- 在存在错误代码的情况下输出参数与 NRVO
- 在完美转发函数中公开参数类型,避免代码重复
- 中断长代码 snprintf 格式和参数
- 使用 const double* const 作为模板参数 - 代码性能问题