존재하는 이유는 무엇입니까 std::decay
? 어떤 상황에서 std::decay
유용합니까?
decay_t<decltype(...)>
auto
추론 할 수 있는 좋은 조합 입니다.
존재하는 이유는 무엇입니까 std::decay
? 어떤 상황에서 std::decay
유용합니까?
decay_t<decltype(...)>
auto
추론 할 수 있는 좋은 조합 입니다.
답변:
<joke> 방사성 std::atomic
유형을 비 방사성 유형으로 붕괴시키는 데 사용됩니다 . </ joke>
N2609 는 제안한 논문이다 std::decay
. 이 논문은 다음과 같이 설명합니다.
간단히 말해서,
decay<T>::type
T가 배열 유형이거나 함수 유형에 대한 참조 인 경우를 제외하고 ID 유형 변환입니다. 이 경우decay<T>::type
함수에 대한 포인터 또는 포인터가 각각 생성됩니다.
동기 부여 예제는 C ++ 03입니다 std::make_pair
.
template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}
문자열 리터럴이 작동하도록하기 위해 값으로 매개 변수를 승인했습니다.
std::pair<std::string, int> p = make_pair("foo", 0);
참조로 매개 변수를 수락 T1
하면 배열 유형으로 추론 된 다음 a 구성 pair<T1, T2>
이 잘못됩니다.
그러나 분명히 이것은 비효율적 인 결과를 초래합니다. 따라서, 값별 decay
전달이 발생할 때 발생하는 변환 세트를 적용하여 매개 변수를 참조로 효율적으로 사용할 수는 있지만 코드가 문자열 리터럴로 작동하는 데 필요한 유형 변환을 얻을 수 있어야합니다. 배열 유형, 함수 유형 등 :
template <class T1, class T2>
inline pair< typename decay<T1>::type, typename decay<T2>::type >
make_pair(T1&& x, T2&& y)
{
return pair< typename decay<T1>::type,
typename decay<T2>::type >(std::forward<T1>(x),
std::forward<T2>(y));
}
참고 : 이것은 실제 C ++ 11 make_pair
구현 이 아닙니다 . C ++ 11 make_pair
도 std::reference_wrapper
s 를 풉니 다 .
템플릿 유형의 매개 변수를 사용하는 템플릿 함수를 처리 할 때 일반적으로 범용 매개 변수가 있습니다. 범용 매개 변수는 거의 항상 한 종류 또는 다른 종류의 참조입니다. 그들은 또한 const-volatile 자격을 갖추고 있습니다. 따라서 대부분의 유형 특성은 예상대로 작동하지 않습니다.
template<class T>
void func(T&& param) {
if (std::is_same<T,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}
int main() {
int three = 3;
func(three); //prints "param is not an int"!!!!
}
http://coliru.stacked-crooked.com/a/24476e60bd906bed
해결책은 다음과 std::decay
같습니다.
template<class T>
void func(T&& param) {
if (std::is_same<typename std::decay<T>::type,int>::value)
std::cout << "param is an int\n";
else
std::cout << "param is not an int\n";
}
decay
예를 들어 배열에 대한 참조에 적용되면 포인터가 생성됩니다. 이러한 종류의 메타 프로그래밍 IMHO에는 일반적으로 너무 공격적입니다.
remove_const_t< remove_reference_t<T> >
경우 사용자 지정 메타 함수로 래핑됩니다.