2016-08-01 5 views
2

저는 작은 도서관에서 일하고 있습니다. 제가해야 할 일 중 하나는 방문객을 일부 데이터에 적용하고 결과를 반환하는 것입니다.`std :: common_type_t <std :: ostream &, std :: ostream &>`은`std :: ostream`이 아니라`std :: ostream`과 같은 이유는 무엇입니까?

일부 오래된 C++ 코드에서 방문자는 typedef return_type을 선언해야합니다. 예를 들어, boost::static_visitor이이를 수행합니다.

최신 코드에서는 모든 방문자가 사용되지 않습니다. C++ 14에서는 보통 decltype(auto)을 사용할 수 있지만 std::common_type과 같은 것을 사용하여 C++ 11에서 할 수 있습니다.

std::common_type의 예제 구현을 C++ 11로 간단히 백 포트하여 리턴 유형을 계산하는 데 사용했습니다. std::common_type_t<std::ostream&, std::ostream&>의 결과가 될 "해야"무엇 cppreference.com

#include <ostream> 
#include <type_traits> 

// decay_t backport 

template <typename T> 
using decay_t = typename std::decay<T>::type; 

// common_type backport 

template <typename T, typename... Ts> 
struct common_type; 

template <typename T> 
struct common_type<T> { 
    using type = decay_t<T>; 
}; 

template <typename T1, typename T2> 
struct common_type<T1, T2> { 
    using type = decay_t<decltype(true ? std::declval<T1>() : std::declval<T2>())>; 
}; 

// TODO: Is this needed? 
/* 
template <typename T> 
struct common_type<T, T> { 
    using type = T; 
}; 
*/ 

template <typename T1, typename T2, typename T3, typename... Ts> 
struct common_type<T1, T2, T3, Ts...> { 
    using type = typename common_type<typename common_type<T1, T2>::type, T3, Ts...>::type; 
}; 

template <typename T, typename... Ts> 
using common_type_t = typename common_type<T, Ts...>::type; 

// static_assert(std::is_same<common_type_t<std::ostream &, std::ostream &>, std::ostream &>::value, "This is what I expected!"); 
static_assert(std::is_same<common_type_t<std::ostream &, std::ostream &>, std::ostream>::value, "Hmm..."); 

int main() {} 

에서 "가능한 구현"을 사용하는 경우

그러나 나는 예상치 못한 결과를 얻을? std::ostream &이 아니어야합니까? 그렇지 않다면 과 clang 3.8.0이 모두 std::ostream이라고 생각하십니까?

참고 : C++ 14에서 "진짜"std::common_type_t을 사용할 때 나는 여전히 std::ostream이 아니라 std::ostream &이 아닙니다.

이 항상 유효한 방법이되도록 std::common_type을 전문화합니까? 그것은 내 프로그램에서 잘 작동하는 것 같지만 해킹처럼 느껴집니다.

+2

관련 : http://stackoverflow.com/q/21975812/2069064,하지만'common_type'은 슬픈 표정 때문에 참조를 제공하지 않습니다. – Barry

+0

고맙습니다 ... 그래서 나는'std :: declval'을 사용해서는 안된다고 생각하십니까? 'decltype (true? std :: forward (std :: declval ()) : std :: forward (std :: decl())')을 사용해야합니까? 사실이게 꽤 까다 롭습니다.'템플릿 을 mini_decay_t = conditional_t ​​< 표준 : is_lvalue_reference :: 값을 사용하여 : –

답변

2

common_type 주변의 내역에 대한 관련 내용은 this question을 참조하고 실제로 참조를 생성하지 않는 이유는 무엇입니까?

std::common_type_t<T, T> 항상 올바른 접근 방식에서 t되도록 std::common_type을 전문으로되어 있습니까?

나는 (당신이 다른 하나를 전문으로 할 수 없기 때문에) 당신이 common_type당신의 구현을 전문으로 의미 가정합니다. 아니, 충분하지 않습니다. common_type<Base&, Derived&>Base&이 되길 원하지만 해당 인스턴스는 사용자의 전문화 과정을 거치지 않습니다.

이 아닙니다. decay을 사용하십시오. decay이있는 이유는 어떤 경우에 declval이 제공하는 놀라운 rvalue 참조를 삭제하기 위해서입니다. 하지만 당신은 좌변 기준을 유지하고자하는 - 그래서 그냥 자신의 형의 특성 추가 :

template <class T> 
using common_decay_t = std::conditional_t< 
    std::is_lvalue_reference<T>::value, 
    T, 
    std::remove_reference_t<T>>; 

그리고 사용하는 대신 정상 decay합니다.

+0

좋아, 나는이 실험 것, 나는 그래도 올바른으로 답변을 표시, 지금은이 버전 함께 일하고 있어요 추측 –

+0

감사합니다 , T, decay_t >; ' –

관련 문제