후행 반환 유형 구문 스타일이 새로운 C ++ 11 프로그램의 기본값이되어야합니까? [닫은]


92

C ++ 11은 새로운 함수 구문을 지원합니다.

auto func_name(int x, int y) -> int;

현재이 함수는 다음과 같이 선언됩니다.

int func_name(int x, int y);

새로운 스타일은 아직 널리 채택되지 않은 것 같습니다 (예 : gcc stl).

그러나이 새로운 스타일은 새로운 C ++ 11 프로그램의 모든 곳에서 선호되어야합니까, 아니면 필요할 때만 사용됩니까?

개인적으로 저는 가능하면 예전 스타일을 선호하지만, 스타일이 혼합 된 코드 기반은 꽤보기 흉해 보입니다.


29
대부분 decltype논쟁에 대한 것입니다.
Cat Plus Plus

CatPlusPlus가 말하는 것 : 귀하의 예에서 사용하는 것은별로 의미가 없습니다
stijn

@Cat Plus Plus 이것은 반환 유형을 파생 할 필요가없는 한 C ++ 03에있는 그대로 두는 것을 의미합니까?
mirk

1
추악한 것은 모든 함수 앞에 "자동"을 지정해야합니다. 파이썬의 "def"에 대한 C ++의 정확한 대답과 같습니까?
Erik Aronesty

답변:


109

후행 반환 유형을 사용해야하는 특정 경우가 있습니다. 특히 람다 반환 유형이 지정된 경우 후행 반환 유형을 통해 지정되어야합니다. 또한 반환 유형 decltype이 인수 이름이 범위 내에 있어야하는를 사용하는 경우 후행 반환 유형을 사용해야합니다 (그러나 일반적 declval<T>으로이 문제를 해결 하는 데 사용할 수 있음 ).

후행 반환 유형에는 몇 가지 다른 사소한 이점이 있습니다. 예를 들어, 전통적인 함수 구문을 사용하는 비 인라인 멤버 함수 정의를 고려하십시오.

struct my_awesome_type
{
    typedef std::vector<int> integer_sequence;

    integer_sequence get_integers() const;
}; 

my_awesome_type::integer_sequence my_awesome_type::get_integers() const
{
    // ...
}

멤버 typedef는 클래스 이름이 앞에 나타날 때까지 범위에 포함되지 않으므로 ::get_integers클래스 제한을 두 번 반복해야합니다. 후행 반환 유형을 사용하는 경우 유형의 이름을 반복 할 필요가 없습니다.

auto my_awesome_type::get_integers() const -> integer_sequence
{
    // ...
}

이 예제에서는 그렇게 큰 문제는 아니지만 인라인으로 정의되지 않은 클래스 템플릿의 멤버 함수 나 긴 클래스 이름이 있으면 가독성에 큰 차이를 만들 수 있습니다.

자신의에서 "신선한 페인트" C ++ 이제 2012 세션, 엘리스 데어 메레디스는 지속적으로 반환 형식을 후행 사용하는 경우, 당신의 모든 기능의 이름이 깔끔하게 정렬 지적 :

auto foo() -> int;
auto bar() -> really_long_typedef_name;

나는 도처에 반환 형식을 후행 사용했습니다 CxxReflect 당신이 코드 외모가 일관되게 사용하는 방법의 예를 찾고 그렇다면, 당신은보고있다 (예를 들어,이 걸릴 수 클래스 ).type


1
아직 합의가없는 것 같지만 새로운 스타일로 CxxReflect를 보는 것이 흥미 롭습니다.
mirk

안녕, 제임스. 이 답변은 아마도 C ++ 14 표준에 비추어 더 정확할 수 있습니다.
Drew Dormann 2015 년

@DrewDormann 무엇을 추가 / 변경 하시겠습니까?
underscore_d

정렬은 실제로 큰 장점입니다. 여기서 의미없는 'auto'를 대체 할 새로운 'func'키워드가 있기를 바랐습니다.
요한 보울

67

다른 사람들이 말한 것 외에도 후행 반환 유형은를 사용할 this수 있습니다.

struct A {
  std::vector<int> a;

  // OK, works as expected
  auto begin() const -> decltype(a.begin()) { return a.begin(); }

  // FAIL, does not work: "decltype(a.end())" will be "iterator", but 
  // the return statement returns "const_iterator"
  decltype(a.end()) end() const { return a.end(); }
};

두 번째 선언에서는 전통적인 스타일을 사용했습니다. 그러나 this해당 위치에서는 허용되지 않으므로 컴파일러에서 암시 적으로 사용하지 않습니다. 따라서는 a.end()정적으로 선언 된 유형을 사용하여 호출 할 오버로드 a를 결정하고 이는 상수가 아닌 버전이됩니다.endvector<int>


2
이것은 (반환 유형에 멤버를 사용하는) 개념의 훌륭하고 깔끔한 데모이지만 C ++ 14에서 유형을 지정하는 것은 변환없이 인라인 정의에서 완전히 중복되기 때문에 재미 있습니다. 이제 전체 반환 유형 추론을 사용할 수 있습니다. : P
underscore_d

27

또 다른 장점은 함수가 함수에 대한 포인터를 반환 할 때 후행 반환 유형 구문을 더 쉽게 읽을 수 있다는 것입니다. 예를 들어, 비교

void (*get_func_on(int i))(int);

auto get_func_on(int i) -> void (*)(int);

그러나 함수 포인터에 대한 유형 별칭을 도입하면 더 나은 가독성을 얻을 수 있다고 주장 할 수 있습니다.

using FuncPtr = void (*)(int);
FuncPtr get_func_on(int i);

10

이 멋진 기사를 참조하십시오 : http://www.cprogramming.com/c++11/c++11-auto-decltype-return-value-after-function.html 게임에서 decltype없이이 구문을 사용할 때 아주 좋은 예 :

class Person
{
public:
    enum PersonType { ADULT, CHILD, SENIOR };
    void setPersonType (PersonType person_type);
    PersonType getPersonType ();
private:
    PersonType _person_type;
};

auto Person::getPersonType () -> PersonType
{
    return _person_type;
}

그리고 Alex Allain의 기사에서 "반환 값이 함수 이전이 아니라 함수의 끝으로 가기 때문에 클래스 범위를 추가 할 필요가 없습니다."에서 빼낸 멋진 설명도 있습니다.

우연히 클래스 범위를 잊어 버리고 더 큰 재난의 경우 다른 PersonType이 전역 범위에 정의 된이 가능한 경우와 비교하십시오.

typedef float PersonType; // just for even more trouble
/*missing: Person::*/
PersonType Person::getPersonType ()
{
    return _person_type;
}

7
이것이 "재해"범주에 속하는지 확실하지 않습니다. 유형이 잘못되면 코드가 컴파일되지 않습니다. 런타임 오류는 심각한 결과를 초래할 수 있습니다. 컴파일 시간 오류는 그리 많지 않습니다.
James McNellis 2012-06-26

4
@JamesMcNellis는 컴파일러 출력을 비교합니다. prog.cpp:13:12: error: prototype for 'PersonType Person::getPersonType()' does not match any in class 'Person'대 컴파일러 prog.cpp:13:1: error: 'PersonType' does not name a type 의 첫 번째 오류는 적어도 저에게는 이해하기가 더 나쁩니다.
PiotrNycz

개인적으로 동의하지 않습니다. 두 번째 메시지를 읽기가 더 어렵고 구현이 선언처럼 보이기를 원합니다.
jrh
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.