템플릿에서 올바른 유형의 데이터를 반환하는 방법은 무엇입니까?


9
#include <iostream>
using namespace std;

template <class X, class Y>
Y big(X a, Y b)
{
   if (a > b)
      return (a);
   else return (b);
}

int main()
{
   cout << big(32.8, 9);
}

여기서는 CPP에서 템플릿을 사용하고 있으므로 big인수 doubleint유형을 무시 하는 함수를 호출 할 때 반환 응답 인을 원합니다 double. 여기에 유형이 32대신 대신 반환 됩니다 32.8.

원하는 출력을 얻는 방법은 무엇입니까? 올바른 반환 유형의 big함수 를 작성하는 방법은 무엇입니까?


1
함수는 하나의 고정 유형 만 리턴 할 수 있습니다 . 런타임에 반환 할 유형을 선택할 수 없습니다.
Jesper Juhl

1
std::max구현 방법을 살펴볼 수 있습니다 . C ++에서 컴파일 타임에 함수의 리턴 유형을 알아야합니다. 따라서이 반환 유형을 매개 변수의 런타임 값에 따라 설정할 수 없습니다. 그렇기 때문에 그러한 기능을 위해서는 동일한 유형 (예 : X는 있지만 Y는 아님)을 갖는 두 매개 변수가 모두 필요합니다.
보리스 달 스타 인

답변:


12

함수는 컴파일 타임에 알고 있어야하는 하나의 리턴 유형 만 가질 수 있습니다. 그러나을 사용 std::common_type하여 두 매개 변수를 모두 암시 적으로 변환 할 수있는 형식을 반환 할 수 있습니다.

그건

#include <type_traits>
template <class X, class Y>
typename std::common_type<X,Y>::type big(X a, Y b)
{
   if (a > b)
      return a;
   else return b;
}

그리고이 사실을 반환하는지 확인합니다 double을 통과 할 때 intdouble우리가 할 수 있습니다 :

int main() {
    auto x = big(4.2,42);
    std::cout << std::is_same<decltype(x),double>::value;
}

어떤 지문

1

추신 : std::common_type스펜스 뒤에 삼항 연산자를 사용할 수 있으므로이 솔루션은 다른 답변 ( auto+ 삼항) 과 크게 다르지 않습니다. 실제 std::common_type장점은 여러 매개 변수를 허용한다는 것입니다.


10

반환 유형은 컴파일 타임에 결정해야합니다. 로 제한되는 경우 조건부 연산자 와 함께 후행 리턴 을 사용할 수 있습니다 .

template <typename X, typename Y>
auto big(X&& a, Y&& b) -> decltype(a > b ? a : b) // ---> like this
{
   return  a > b ? a : b;
}

라이브보기


그러나 이상에 액세스 auto할 수 있으면 다음과 같이 조건부 연산자와 함께 사용하면 컴파일러가 올바른 유형을 추론하기 때문에 충분합니다.

template <typename X, typename Y>
auto big(X a, Y b)
{
   return  a > b ? a : b;
}

라이브보기


적어도 C ++ 14부터는 후행 리턴 유형이 필요하지 않습니다.
스웨덴어

@walnut 좋은 지적. 또 다른 옵션은 전달 참조입니까?
여조

1
@JeJo 예, 인수도 수정하지 않고 반환 유형이 여전히 lvalue 참조 일 것이므로 (아마도 아닌 경우도 있지만) 괜찮습니다 const.
호두

더 이상 적용되지 않으므로 주석을 제거했지만 매개 변수 별 값을 사용할 수 없다는 경고에 대한 답변을 추가하는 것이 좋습니다.
호두

코드에 사람의 외모 경우 전달 된 매개 변수 인 얻을 것이다 반환 형식 사람이 결정하는 것으로 보인다 없는 경우! a가 b보다 큰 경우에도 항상 배가됩니다.
클라우스

4

반품 유형을 표시 Y하고int 두 번째 매개 변수로, 당신은 명확하게 표시 한 Y입니다 int. 여기서 놀라운 일이 없습니다.

#include <iostream>

template <typename X, typename Y>
decltype(auto) big(const X& a, const Y& b)  // return type can just be auto as well 
{
    return a > b ? a : b;
}

int main()
{
    std::cout << big(32.8, 9) << '\n';
    std::cout << big(9, 32.8) << '\n';
    std::cout << big(32.8, 90) << '\n';
    std::cout << big(90, 32.8) << '\n';
}

네 개의 정확한 값이 모두 화면에 인쇄됩니다.

https://godbolt.org/z/fyGsmo

주목해야 할 것은 서로 비교할 수있는 유형에 대해서만 작동한다는 것입니다. 즉, 컴파일러는 비교를 위해 한 유형을 다른 유형으로 암시 적으로 변환합니다.

중요 : 정의되지 않은 동작을 피하기 위해 매개 변수를 참조해야합니다. 이것은 내가 고집스럽게 생각하는 리턴 타입과 관련이 있습니다. decltype(auto)형식에 대한 참조를 반환 할 수 있습니다. 함수 (인수 카운트)에 로컬로 무언가를 반환하면 정의되지 않은 동작이 발생합니다.


@walnut 실수로 참조를 반환하는 것이이 사이트에서 만드는 것보다 훨씬 어렵습니다. 그러나 정의되지 않은 동작에 대해 아는 것이 좋습니다. 어쨌든 내가 작성한 코드가 아닌 것 같습니다. 질문에 대한 답변입니다.
스웨덴어

1
아 나는 당신의 이전 의견을 두 가지 별개의 요점으로 읽었으며 효과와 원인은 아닙니다. 적절한 편집을 할 수 있습니다.
스웨덴어

면책 조항을 추가했습니다.
스웨덴어

2

이것은 모든 상황에서 정확한 상황에 맞는 올바른 해결책이 아닙니다. 다른 답변은 원하는 것에 훨씬 더 가깝습니다.

당신은 그러나 정말 어떤 이유로 런타임에 완전히 다른 유형을 반환해야, (이후 올바른 해결책 )를 사용하는 std::variant형태 보증 된 노동 조합의 일종 인을.

#include <variant>

template <typename X, typename Y>
std::variant<X, Y> max(X a, Y b) {
  if (a > b)
    return std::variant<X, Y>(std::in_place_index_t<0>, a);
  else
    return std::variant<X, Y>(std::in_place_index_t<1>, b);
}

그러면 반환 값을 처리하기 위해 호출자가 onus를 사용 std::visit합니다.


-2

Y는 int이므로 int를 반환하고 32.8을 캐스팅합니다. big을 호출하면 32,82는 float이지만 8은 int이고 함수 반환 유형은 Y이며 int입니다.

런타임에 어떤 유형의 큰 리턴을 알아야하는지에 따라이 문제를 실제로 해결할 수 없으므로 a와 b를 다음과 같이 같은 유형으로 만드십시오.

    #include <iostream>
    using namespace std;

    template <typename X>

    X big (X a, X b)
    {
    if (a>b)
    return a;

    else return b;
    }

    int main()
    {
    cout<< big (32.8, 9.0);
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.