我正在编写类似的代码:
template<bool B, typename IfT, typename ThenT>
using conditional_t = std::conditional_t<B, IfT, ThenT>;
template <bool B,
typename IfT, typename ThenT>
constexpr auto conditional_v(IfT&& t1, ThenT&& t2)
-> conditional_t<B, IfT, ThenT> {
if constexpr (B) {
return t1;
} else {
return t2;
}
}
如果通过conditional_v<true>(0, 1)
之类的值传递,我们可以得到
template<>
inline constexpr conditional_t<true, int, int> conditional_v<true, int, int>(int && t1, int && t2)
{
if constexpr(true) {
return t1;
}
}
如果通过引用,例如conditional_v<true>(i, j)
,我们将得到
template<>
inline constexpr conditional_t<true, int &, int &> conditional_v<true, int &, int &>(int & t1, int & t2)
{
if constexpr(true) {
return t1;
}
}
[当我指的是stl时,例如max
template< class T >
constexpr const T& max( const T& a, const T& b );
它们大多由const T&
而不是T&&
传递。
所以我得到一个问题:在我的情况下是否应该使用const T&
(就像conditional_t,conditional_v设计为在comipler时选择一个初始值一样。)
请考虑以下代码:
int foo = bar(); // some function that returns a value we don't know
int foo2 = std::max(foo, 100); // make sure it's no more than 100
如果std::max
接受&&
作为参数,您将如何编写该代码?
T &&的引入是通过“窃取”传递的对象资源来避免不必要的复制。假设对象rhs具有指向某些已分配资源rhs.p的指针,则典型用法是
void steal (T&& rhs){
p=rhs.p;
rhs.p=nullptr;
}
由于在您的情况下std::max
不打算更改参数,因此没有理由通过右值引用传递参数。同样,您将无法将其与左值引用一起使用。除了命名变量之外,const T&
还允许我们传递临时变量。例如
struct Test {};
Test returnObject(){
Test t;
return t;
}
int main(){
Test x;
Test& y=x;
Test&& z=x;//error cannot bind rvalue to lvalue
Test& r=returnObject();// error: cannot bind lvalue to rvalue
const Test& a=returnObject();// OK
Test&& b=returbObject();// OK
}