문제

조건부 포인터 역참조 기능을 구현하려고 합니다.기본 아이디어는 다음과 같습니다.

return is_pointer(arg) ? *arg : arg

필요한 전문화의 수를 제한하기 위해 다음과 같은 경우에 rvalue 참조를 사용하려고 합니다. arg 포인터가 아닙니다.현재 구현은 다음과 같습니다( 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

당신의 도움을 주셔서 감사합니다.

도움이 되었습니까?

해결책

내가 이해하는 한도에서는

template <T>
void foo(T&&)

즉, 만약 T lvalue이면 참조로 추론됩니다(T = int*& 귀하의 경우) 및 참조 축소 후 int*&&& 일반 lvalue 참조를 생성합니다. int*&.그렇지 않은 경우 이 구문은 모든 것을 rvalue 참조로 캡처합니다.요점은 lvalue를 lvalue 참조에 바인딩하고 rvalue를 rvalue 참조에 바인딩하는 것입니다.

그리고 is_pointer<int*&> 사실이 아닙니다.따라서 신청해 볼 수도 있습니다. remove_reference<T>.

다른 팁

첫 번째 과부하 T는 int * &를 추론하고 있습니다.enable_if 테스트 및 출력에서 remove_reference<T>::type를 사용하려면 첫 번째 과부하를 사용해보십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top