std :: pair <auto, auto> 반환 유형 함수 f는 std::pair템플릿 매개 변수에

에서 놀고 auto있었습니다 std::pair. 아래 코드에서 함수 fstd::pair템플릿 매개 변수에 따라 유형 중 하나를 반환해야합니다 .

실제 예 :

실시 예 1

template <unsigned S>
auto f()
{
    if constexpr (S == 1)
        return std::pair{1, 2}; // pair of ints
    else if constexpr (S == 2)
        return std::pair{1.0, 2.0}; // pair of doubles
    else
        return std::pair{0.0f, 0.0f}; // pair of floats
}

이것은 gcc 9.2, gcc 10.0, clang 9.0 및 clang 10.0에서 작동합니다.

다음으로, std::pair명확한 이유로 반환 유형을 명시 적으로 작성하고 싶었습니다 .

실시 예 2

template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return {1, 2};
    /* ... */
}

gcc 9.2 / 10.0과 clang 9.0 / 10.0 모두 컴파일에 실패했습니다.

gcc 9.2

error: invalid use of 'auto'
error: template argument 1 is invalid // first argument (auto) of std::pair
error: template argument 2 is invalid // second argument (auto) of std::pair
error: cannot convert '<brace-enclosed initializer list>' to 'int' in return

마지막 오류 메시지에서 GCC 9.2은 믿는 것 같다 std::pair<auto, auto>입니다 int. 이것을 어떻게 설명 할 수 있습니까?

gcc 10.0

error: returning initializer list

이 오류는 이해할 만하지 만 생성자 std::pair가 호출 될 것으로 기대 했거나 여기에 누락 된 것이 있습니까?

클랑 9.0 및 10.0

'auto' not allowed in template argument
excess elements in scalar initializer
no matching function for call to 'f'

좋아, clang은 이것을 좋아하지 않습니다. 두 번째 오류 메시지에서 clang은 반환 유형이이라고 생각합니다 int.

마지막으로 gcc 10.0으로 컴파일하여 얻은 오류를 수정하기 위해 std::pair명시 적으로 반환하기로 결정했습니다 .

실시 예 3

template <unsigned S>
std::pair<auto, auto> f()
{
    if constexpr (S == 1)
        return std::pair{1, 2};
    /* ... */
}

클랑 9.0 및 10.0

이전과 동일하지만 추가로

no viable conversion from returned value of type 'std::pair<int, int>' to function return type 'int'

여기 clang은 여전히 ​​우리가 int?

gcc 9.2

이전과 동일합니다.

gcc 10.0

효과가있다!

일부 기능은 여전히 ​​구현해야하거나 위에서 설명한 상황 중 하나에서 옳고 다른 컴파일러가 있습니까? 제 생각에는 예제 2가 작동해야합니다. 아니면 안 돼요?



답변

문법 :

std::pair<auto, auto> f() { return std::pair(1, 2); }
~~~~~~~~~~~~~~~~~~~~~

원래 Concepts TS의 일부 였지만 C ++ 20의 일부인 Concepts 제안에는 포함되지 않았습니다. 따라서 C ++ 20의 유일한 자리 표시 자 유형은 auto(및 이와 유사한 변형 auto**) decltype(auto)및 제한된 자리 표시 자 Concept auto및 변형입니다. 이러한 종류의 중첩 자리 표시 자 유형은 매우 유용하지만 C ++ 20의 일부가 아니므로 함수 선언이 잘못 구성됩니다.

gcc는 개념 TS를 구현했기 때문에 gcc가 허용하며이 기능을 유지하기로 결정한 것 같습니다. clang은 TS를 구현하지 않았으므로 TS를 구현하지 않았습니다.

어느 쪽이든, 이것은 :

std::pair<auto, auto> f() { return {1, 2}; }

항상 잘못된 것입니다. 구문의 의미는 반환 유형을 추론 한 다음 pair<T, U>일부 유형 T과 일치하도록 요구한다는 것 U입니다. 우리는 기본적으로 발명 된 기능을 호출하려고합니다.

template <typename T, typename U>
void __f(std::pair<T, U>);

__f({1, 2}); // this must succeed

그러나 {1, 2}braced-init-list에는 유형이 없습니다. 아마도 이것은 (이와 같은 간단한 경우에는 이해하기 쉽기 때문에) 탐구해야 할 것이지만 결코 허용되지 않았습니다. 따라서 그것을 거부하는 것은 어느 쪽이든 맞습니다.

마지막으로 :

gcc 9.2 std::pair<auto, auto>int. 이것을 어떻게 설명 할 수 있습니까?

어떤 이유로 (아마도 암시적인 C 레거시로 인해 int) gcc가 유형을 인식하거나 이해하지 못하면 int오류 메시지에서 자리 표시 자로 만 사용 됩니다. 명백히 int소스 코드가 아닌 gcc이기 때문에 이것은 매우 혼란 스럽습니다 . 그러나 그것이 바로 그 방법입니다.


답변