我发现了在标准C ++ 11中使用可选引用的技巧。 你认为这种技术是否可靠,并且根据C ++标准很好地定义了行为?
// Optional reference using C++11
// V. Reverdy - 2013
#include <iostream>
#include <type_traits>
template <class T = int, class = typename std::enable_if<std::is_same<typename std::decay<T>::type, int>::value>::type>
void f(T&& n = T())
{
std::cout<<"--------"<<std::endl;
std::cout<<"is const = "<<std::is_const<T>::value<<std::endl;
std::cout<<"is reference = "<<std::is_reference<T>::value<<std::endl;
std::cout<<"is lvalue reference = "<<std::is_lvalue_reference<T>::value<<std::endl;
std::cout<<"is rvalue reference = "<<std::is_rvalue_reference<T>::value<<std::endl;
std::cout<<"--------"<<std::endl;
n *= 2;
}
int main(int argc, char* argv[])
{
int n = 42;
std::cout<<"n = "<<n<<std::endl;
f();
std::cout<<"n = "<<n<<std::endl;
f(n);
std::cout<<"n = "<<n<<std::endl;
return 0;
}
结果是:
n = 42
--------
is const = 0
is reference = 0
is lvalue reference = 0
is rvalue reference = 0
--------
n = 42
--------
is const = 0
is reference = 1
is lvalue reference = 1
is rvalue reference = 0
--------
n = 84
它似乎适用于liveworkspace上的所有编译器:LWS
答案 0 :(得分:2)
笏。
首先,你所拥有的“实现”可能会更简单,例如,重载。其次,它与可选参考完全不同。可选引用是一个值,在运行时可能包含也可能不包含引用 。行为是明确定义的,但它既不可取,也不是可选参考。将临时引用绑定作为默认参数在某些情况下很好,但距离可选引用的距离是十亿英里。
答案 1 :(得分:1)
它是明确定义的,是的,因为“通用引用”(请注意这是一个非标准术语的事实)可以解析为rvalue引用,因此绑定到temporaries,但是你'不要创建“可选参考”。
引用必须始终初始化并且必须始终绑定到对象,它们不能“绑定或不绑定”(这是我对“可选引用”的含义的直观理解)。
在这里,您只是将该引用绑定到临时。你所做的相当于以下几点:
template<typename T> void f(T&& t) { ... }
void f() { f(int()); }
如果你想说你现在能够创建一个接受引用的函数,并且可以在不提供任何参数的情况下调用它 - 这是IMO更正确的方式 - 那么这是真的,但我不会'认为这是一个突破性的发现。
即使在C ++ 03中,您也可以执行类似的操作,但仅限于引用const
:
template<typename T>
void f(T const& = T()) { ... }
由于C ++ 11引入了可以绑定到temporaries(rvalue引用)的非const
引用,因此会出现自然泛化,这是您的技术所利用的。