3

표준 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

실제 사용 사례가 있습니까? – Mat

+1

재미있는 부분은'int','int &','int &&'와'int const &'사이에'T' 타입 타입이 있습니다. 여러분이 아무것도 전달하지 않으면'int' 선택이 일어납니다. 매개 변수없이'int'를 얻는 이유는'T'가 더 이상 추론되지 않고'T &&'가 더 이상 유형 공제 문맥에서 사용되지 않는다는 것을 의미하는 템플릿 인자의 기본값이 사용되기 때문입니다. 이 함수에서'std :: is_reference :: value'을 시도해보십시오. 기술의 단점은'T'가 때로는 공제 문맥에 있고 때로는 그렇지 않다는 것입니다. – Yakk

답변

2

와트.

첫째로, "달성하다"는 것이 과부하로 인해 훨씬 ​​간단해질 수 있습니다. 두 번째로 선택적인 참조 과 전혀 같지 않음. 선택적 참조는 실행시에 참조 을 포함 할 수도 있고 포함하지 않을 수도있는 값입니다. 행동은 잘 정의되어 있지만 바람직하지 않으며 선택적 참조가 아닙니다. 임시 인수에 대한 참조를 기본 인수로 바인딩하는 것은 일부 상황에서는 좋지만 선택적 참조로부터 10 억 마일에 해당합니다.

1

"범용 참조"(비표준 용어라는 사실을 염두에두기)은 rvalue 참조로 변환 할 수 있으므로 임시로 바인딩 할 수 있지만 잘 정의되어 있지 않습니다. "optional reference".

참조는 항상 초기화되어야하며 항상 객체에 바인딩되어야하며 "바인딩되거나 바인딩되지"않을 수 있습니다. 이는 "선택적 참조"의 의미에 대한 직관적 인 이해입니다.

여기서 참조를 임시로 바인딩하면됩니다. 당신이 한 일은 동등 않습니다 :

template<typename T> void f(T&& t) { ... } 
void f() { f(int()); } 

당신은 당신이 지금 참조를 허용하는 기능을 만들 수 있습니다 및 인수 제공하지 않고 호출 할 수 있습니다 말을 의미하는 경우 - IMO 더 정확한 방법입니다 그것을 말하면 - 그렇습니다. 그러나 나는 그것을 깨는 발견으로 생각하지 않을 것입니다. 심지어 C++ 03 비슷한 뭔가를 할 수있는

, 비록 참조에 대한에 const 전용 : 임시직 (를 rvalue 참조)에 결합 할 수있는 C++ 11 도입 비 const 참조 이후

template<typename T> 
void f(T const& = T()) { ... } 

, 당신의 기술이 이용하고있는 자연적인 일반화가 뒤 따른다.

관련 문제