1

조건부 포인터 역 참조 함수를 구현하려고합니다. 필요한 전문의 수를 제한하기 위해rvalue 참조로 함수 템플릿 전문의 동작

return is_pointer(arg) ? *arg : arg 

, 나는 arg 포인터하지 않은 경우에를 rvalue 참조를 사용하려고 해요 : 다음과 같이 기본 개념이다. 여기에 내 현재 구현합니다 (std::cout 전적으로 목적을 디버깅이 있습니다) :

template< typename T > 
inline typename std::enable_if< std::is_pointer<T>::value == false, T >::type deref(T&& t) 
{ 
    std::cout << std::is_pointer<T>::value << std::endl; 
    std::cout << typeid (T).name() << std::endl; 
    return t; 
} 

template< typename T > 
inline typename std::enable_if< std::is_pointer<T>::value == true, typename std::remove_pointer<T>::type& >::type deref(T t) 
{ 
    std::cout << std::is_pointer<T>::value << std::endl; 
    std::cout << typeid (T).name() << std::endl; 
    return *t; 
} 

는 지금, 나는 GCC 4.6에 따라 다소 이상한 행동을 얻는다. 첫 번째 오버로드는 비 포인터 유형과 포인터 유형 모두에 사용됩니다. 분명히, 포인터 타입을 사용할 때 두 번째 오버로드와 충돌합니다. 내가 두 번째를 주석하고 ...하여 첫 번째를 사용하여 다음과 같은

int q; 
int *p = &q; 
deref(p); 

를 호출 할 경우 ... 해당 콘솔 출력은 다음과 같습니다

0 
Pi 

이 어떻게 가능 있다는 것입니다 비 포인터 (std::is_pointer에 따라) 유형은 (typeid에 따라) 같은 컨텍스트의 포인터 유형입니까? 두 포인터 오버로드간에 std::is_pointer이 비 포인터 유형 인 p을 잘못보고하여 충돌이 발생합니다. 내가 처음 과부하의 표준 참조 r 값 참조 교체 할 때 또한 :

inline typename std::enable_if< std::is_pointer<T>::value == false, T >::type deref(T& t) 

그것은 더 이상 두 번째 오버로드와 충돌하지 않습니다 ... 난 그저 무슨 일이 일어나고 있는지하지 않습니다. 당신의 도움에 대한

1 
Pi 

감사 : (예상되는대로) 두 번째 과부하 수율을 사용하는 방법으로.

답변

3

는 지금까지 내가 이해

template <T> 
void foo(T&&) 

T는 좌변 인 경우, 그것은 (귀하의 경우 T = int*&) 기준으로 추론하고 int*&&&의 붕괴 참조 후 정기적 좌변 참조 int*&를 산출된다는 것을 의미합니다. 그렇지 않다면,이 구문은 rvalue reference로 무엇이든 잡을 것입니다. 점은 lvalue 참조와 rvalues를 lvalue 참조에 바인딩하는 것입니다.

is_pointer<int*&>이 사실이 아닙니다. 그러므로 remove_reference<T>을 신청 해보십시오.

+0

주셔서 감사합니다. enable_if 조건에서 remove_reference를 사용할 때 실제로 컴파일됩니다. 나는 당신이 의미하는 바를 정확하게 얻지 못합니다 : – pmjobin

+0

@pmjobin : By ... what? – GManNickG

2

첫 번째 오버로드에서 T는 int * &으로 추론됩니다. 첫 번째 오버로드를 시도하여 enable_if 테스트 및 출력에 remove_reference<T>::type을 사용하십시오.