반환 유형으로 decltype
덕분에 C++ 11에서는 데코레이터를 매우 쉽게 소개 할 수있었습니다. 내가 장식 다른 종류의 여러 번, 내가 먼저 간단하게 base
모든 것을 전달하는 decorator
클래스를 소개 그렇게 때문에왜 자동 리턴 유형이 과부하 해결을 변경합니까?
struct base
{
void fun(unsigned) {}
};
내가 추가 기능을 장식 할, 그리고 : 예를 들어,이 클래스를 고려하십시오. 실제 코드에서는 std::shared_ptr
을 통해 이루어 지므로 장식을 제거하고 "알몸"개체를 복구 할 수 있으며 모든 것이 템플리트 화됩니다.
#include <utility> // std::forward
struct decorator
{
base b;
template <typename... Args>
auto
fun(Args&&... args)
-> decltype(b.fun(std::forward<Args>(args)...))
{
return b.fun(std::forward<Args>(args)...);
}
};
완벽한 전달 및 decltype
은 훌륭합니다. 실제 코드에서는 실제로 함수의 이름 만 필요한 매크로를 사용합니다. 나머지는 모두 상용구입니다.
그리고, 나는 (derived
가 부적절 동의하지만, 상속을 통해하지 불구하고, derived
은 뿐인 것을 base
의 이해를 도움) 내 객체에 기능을 추가하는 derived
클래스를 도입 할 수 있습니다.
struct foo_t {};
struct derived : decorator
{
using decorator::fun; // I want "native" fun, and decorated fun.
void fun(const foo_t&) {}
};
int main()
{
derived d;
d.fun(foo_t{});
}
그런 다음 C++ (14)는 간단한 방법으로 사물을 쓸 수 반환 형식 공제, 함께 온 :에게 다음을
struct decorator
{
base b;
template <typename... Args>
auto
fun(Args&&... args)
{
return b.fun(std::forward<Args>(args)...);
}
};
그리고 : 전달 함수의 decltype
부분을 제거 휴식. 예, 적어도 GCC와 연타 모두에 따라이 :
template <typename... Args>
auto
fun(Args&&... args)
-> decltype(b.fun(std::forward<Args>(args)...))
{
return b.fun(std::forward<Args>(args)...);
}
};
이 일치하지 않는 (그리고 문제가되지 auto
대 decltype(auto)
입니다) :
template <typename... Args>
auto
fun(Args&&... args)
{
return b.fun(std::forward<Args>(args)...);
}
};
과부하 해상도는 것 같다 완전히 다른과는 다음과 같이 종료 :
clang++-mp-3.5 -std=c++1y main.cc
main.cc:19:18: error: no viable conversion from 'foo_t' to 'unsigned int'
return b.fun(std::forward<Args>(args)...);
^~~~~~~~~~~~~~~~~~~~~~~~
main.cc:32:5: note: in instantiation of function template specialization
'decorator::fun<foo_t>' requested here
d.fun(foo_t{});
^
main.cc:7:20: note: passing argument to parameter here
void fun(unsigned) {}
^
내가 실패 이해 : 내 전화 (d.fun(foo_t{})
가) 서명과 완벽하게 일치하지 않는 경우 derived::fun
은 const foo_t&
이므로 매우 열심히 decorator::fun
이 맞습니다 (우리는 Args&&...
이 완벽하게 일치하지 않는 것을 바인딩하는 데 극도로 성급한 방법을 알고 있습니다). 그래서 foo_t
을 처리 할 수없는 base::fun
에게 전달합니다.
나는 foo_t
대신 const foo_t&
의를 취할 derived::fun
을 변경하는 경우
derived::fun
와 decorator::fun
사이에 경쟁이 있다는 것을 보여주는 예상대로 작동합니다. 그러나 왜 도대체 리턴 유형 공제와 함께이 쇼를합니까 ??? 그리고 더 정확하게는 왜이위원회에서 선택한 행동입니까?
는 Coliru에, 일을 더 쉽게 만들려면 :
감사합니다!
@Nawaz : 팁 주셔서 감사. 여기서는 차이가 없습니다. – akim
'auto'도'decltype (auto)'도 안되는'decltype (b.fun (std :: forward (args) ...))'는 * SFINAE * 표현식으로 작동합니다. –
Piotr S.의 의견 : 그것은 의도적 인 것입니다. SFINAE가 작동하려면 함수 본문을 보지 않고 반환 유형을 사용할 수 있어야합니다. 리턴 람다를 사용하려면 함수 본문을 보지 않고 반환 유형을 사용할 수 없어야합니다. 람다를 되돌려주는 것이 SFINAE보다 더 중요하다는 결정이 내려졌습니다. – hvd