2011-02-23 3 views
12

선언되지 않았다면 constexpr, std::forward은 인수를 전달하는 모든 함수에 대해 constexpr-ness를 무시합니다. std::forwardconstexpr으로 선언되지 않으므로 constexpr-ness를 유지할 수 있습니까?std :: forward가 constexpr-ness를 버리는 이유는 무엇입니까?

예 : (g 테스트 ++ 스냅 샷 2011-02-19)

#include <utility> 

template <typename T> constexpr int f(T x) { return -13;} 
template <typename T> constexpr int g(T&& x) { return f(std::forward<T>(x));} 

int main() { 
    constexpr int j = f(3.5f); 
    // next line does not compile: 
    // error: ‘constexpr int g(T&&) [with T = float]’ is not a constexpr function 
    constexpr int j2 = g(3.5f); 
} 

참고 : 기술적으로, 그렇게 (즉, g에 std::forward이 가지고주의처럼, 예를 들어 std::forward constexpr을 쉽게 만들 수있을 것입니다) fix::forward에 의해 대체되었습니다 :

#include <utility> 

namespace fix { 
    /// constexpr variant of forward, adapted from <utility>: 
    template<typename Tp> 
    inline constexpr Tp&& 
    forward(typename std::remove_reference<Tp>::type& t) 
    { return static_cast<Tp&&>(t); } 

    template<typename Tp> 
    inline constexpr Tp&& 
    forward(typename std::remove_reference<Tp>::type&& t) 
    { 
    static_assert(!std::is_lvalue_reference<Tp>::value, "template argument" 
      " substituting Tp is an lvalue reference type"); 
    return static_cast<Tp&&>(t); 
    } 
} // namespace fix 

template <typename T> constexpr int f(T x) { return -13;} 
template <typename T> constexpr int g(T&& x) { return f(fix::forward<T>(x));} 

int main() { 
    constexpr int j = f(3.5f); 
    // now compiles fine: 
    constexpr int j2 = g(3.5f); 
} 

내 질문이있다 : 왜 std::forwardfix::forward 같이 정의되지 않는 이유는 무엇입니까?

주 2 :이 질문은 다소하지 constexpr되는 것은 std::tuple이 우변과의 CSTR를 호출하여 생성 할 수없는 이유를 기술적 인 이유입니다 내 다른 question about constexpr std::tuplestd::forward으로 관련이있다, 그러나 여기이 질문에 분명히 (훨씬) 더 일반적이다.

+1

[_ [A-Z]'로 시작하는 식별자는 컴파일러 구현 자에게 예약됩니다. 귀하의 프로그램은 부적절한 형태입니다. –

+3

_T는 매크로가있는 Windows로 옮겨야하는 경우에 특히 불쾌합니다. –

+1

@Matthieu M, @Bo Persson Thanks. 다른 사람들이 코드를보다 안전하고 쉽게 시도 할 수 있도록 T라는 이름으로 _T를 대체했습니다. – Lars

답변

10

일반적인 답은 C++위원회의 라이브러리 워킹 그룹이 새로운 핵심 기능을 사용할 수있는 기회를 모색하는 작업 초안을 통해 철저한 트롤을 수행하지 않았다는 것입니다. 이러한 기능은 사람들이 가능한 용도를 볼 시간과 경향이있는 곳에서 사용되었지만 철저한 검사를위한 시간은 없습니다.

November 2010 mailing에있는 것과 같이 작동 중에 constexpr의 추가 사용과 관련된 몇 가지 문서가 있습니다.

+0

감사합니다. 나는 관련 문서 [N3231] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3231.html)를 이미 알고 있었지만 표준에 대해서는 20.3.3 절을 언급하지 않았다. ::앞으로. - 당신이 제공하는 것은 더 "사회적 이유"입니다. 나는 "개념적 이유"에 관심이있다. 즉, std :: forward constexpr를 만드는 데 잘못된 것이 있는가, 아니면 괜찮을 까? – Lars

+4

나는 언뜻보기에 왜 어떤 이유를 볼 수 없습니다. –

+0

constexpr 함수에서 함수 포인터를 전달하고 호출 할 수있게 해주는 문제 보고서가 있습니다. 리터럴 함수 객체 유형은 constexpr이 될 수 있습니다. std :: forward가 아닌 constexpr은 불행한 것 같습니다. –

관련 문제