2014-04-08 6 views
0

완벽한 전달을 시도하면서 템플릿 차감 문제가 발생했습니다. 그것은 내가 템플릿 함수의 서명 const를 추가하지 않을 경우 동안C++ 11 : 템플릿 공제 및 const 유형

다음은

template<typename T> 
void forwarder(T&& x) 
{ 
} 

int main() 
{ 
    int x = 42; 
    forwarder(x); 
    return 0; 
} 

를 컴파일합니다. forwarder<int&>(x)

내가 유용 할 수 있습니다, 심지어 템플릿에 const을 추가 생각하지만, 내 : 나는 템플릿 매개 변수로 int&을 specifiying에 의해 작동시킬 수 g++

test.cc: In function ‘int main()’: 
test.cc:11:16: error: cannot bind ‘int’ lvalue to ‘const int&&’ 
test.cc:4:6: error: initializing argument 1 of ‘void forwarder(const T&&) [with T = int]’ 

에서

template<typename T> 
void forwarder(const T&& x) // adding const here 
{ 
} 

int main() 
{ 
    int x = 42; 
    forwarder(x); 
    return 0; 
} 

오류 메시지 머리가 아프다.

템플릿 공제에 대한 확실한 이해를 가진 사람이 여기에서 무슨 일이 일어나고 있는지 그리고 템플릿 공제와 함께 const를 사용할 수 있고 실용적인지 여부를 알려줄 수 있습니까?

+0

그냥 궁금해서, 왜 그것이 CONST의 경우를 rvalue (이동) 기준을 만들고있다? 이동 참조의 포인트는 보통 더 이상 사용할 수없는 지점으로 원래의 객체를 변경하는 것입니다. – Julius

+1

여기서 이해할 것은 많지 않습니다 :'T && '에 적용 할 수없는 특별한 규칙이 있습니다 :'T const &&':) In Standardese, 즉 [temp.deduct.call]/3 "'P'가 cv-unqualified 템플릿 매개 변수에 대한 rvalue 참조이고 인수가 lvalue이면에서"lvalue reference to A ""유형이 사용됩니다. 유형 공제를위한 'A'의 장소. " – dyp

+0

이동 참조의 요점은 원래 개체를 더 이상 사용할 수없는 지점으로 변경하는 것입니다. – Julius

답변

0

특정 과부하 선택하는 유형 특성 및 태그 파견을 개시 최고 :

template<typename T> 
void forwarder_impl(T&& x, std::true_type, std::true_type) 
{ 
    std::cout << "rvalue reference to const\n"; 
} 
template<typename T> 
void forwarder_impl(T&& x, std::true_type, std::false_type) 
{ 
    std::cout << "rvalue reference to non-const\n"; 
} 
template<typename T> 
void forwarder_impl(T&& x, std::false_type, std::true_type) 
{ 
    std::cout << "lvalue reference to const\n"; 
} 
template<typename T> 
void forwarder_impl(T&& x, std::false_type, std::false_type) 
{ 
    std::cout << "lvalue reference to non-const\n"; 
} 

template<typename T> 
void forwarder(T&& x) 
{ 
    forwarder_impl(
     std::forward<T>(x), 
     typename std::is_rvalue_reference<decltype(x)>::type(), 
     typename std::is_const<typename std::remove_reference<decltype(x)>::type>::type() 
    ); 
} 

int main() 
{ 
    const int x = 42; 
    int y = 42; 
    forwarder(std::move(x)); 
    forwarder(std::move(y)); 
    forwarder(x); 
    forwarder(y); 
} 

출력 :

rvalue reference to const 
rvalue reference to non-const 
lvalue reference to const 
lvalue reference to non-const 

라이브 예 : http://ideone.com/vHZ7oC

왜 당신이 이제까지 원할 것까지를 그것은 수수께끼로 남아 있습니다.

template<typename T> 
typename std::enable_if< 
    std::is_const<typename std::remove_reference<T>::type>::value 
>::type 
forwarder(T&& x) 
{ 
    auto value_cat = std::is_rvalue_reference<decltype(x)>::value ? "r" : "l"; 
    std::cout << value_cat << "value reference to const\n"; 
} 

int main() 
{ 
    const int x = 42; 
    forwarder(std::move(x)); 
    forwarder(x); 
    //int y = 42; 
    //forwarder(std::move(y)); //compile-time error 
    //forwarder(y);    //compile-time error 
} 

출력 :

rvalue reference to const 
lvalue reference to const 
당신이 forwarder 만 CONST에 대한 참조를 받아, 당신은 T&&의 보편성을 유지하면서 그렇게 할 SFINAE를 사용할 수있는 제한하고 싶다면


http://ideone.com/t5UoZE http://ideone.com/jc2Ek2

다시 한 번, 그러한 일에 대한 동기는 나보다 앞서 있습니다.


자료 : https://www.google.com/search?q=scott+meyers+universal+references

관련 문제