수색…


통사론

  • [[details]] : 단순한 인수없는 속성

  • [[details (arguments)]] : 인수가있는 속성

  • __attribute (세부 정보) : 비표준 GCC / Clang / IBM 특정

  • __declspec (세부 정보) : 비표준 MSVC 관련

[[noreturn]]

C ++ 11

C ++ 11에서는 [[noreturn]] 특성을 도입했습니다. 함수가 return 문을 실행하거나 호출 본문 인 경우 끝에 도달하여 함수가 호출자에게 반환되지 않음을 나타내는 함수에 사용될 수 있습니다. void 함수에 적용되지 않는다는 점에 유의해야합니다. 호출자에게 돌아 가면 아무 값도 반환하지 않습니다.) 이러한 함수는 std::terminate 또는 std::exit 를 호출하거나 예외를 throw하여 std::terminate 될 수 있습니다. 그러한 함수가 longjmp 를 실행하여 리턴 할 수 있다는 점도 주목할 가치가 있습니다.

예를 들어, 아래 함수는 항상 예외를 던지거나 std::terminate 호출하므로 [[noreturn]] 대한 좋은 후보가됩니다.

[[noreturn]] void ownAssertFailureHandler(std::string message) {
    std::cerr << message << std::endl;
    if (THROW_EXCEPTION_ON_ASSERT)
        throw AssertException(std::move(message));
    std::terminate();
}

이러한 종류의 기능을 사용하면 컴파일러는 코드가 실행되지 않는다는 것을 알고있는 경우 return 문없이 함수를 종료 할 수 있습니다. 여기, 아래 코드에서 ownAssertFailureHandler (위에 정의 된) 호출이 결코 반환되지 않기 때문에 컴파일러는 해당 호출 아래에 코드를 추가 할 필요가 없습니다.

std::vector<int> createSequence(int end) {
    if (end > 0) {
        std::vector<int> sequence;
        sequence.reserve(end+1);
        for (int i = 0; i <= end; ++i)
            sequence.push_back(i);
        return sequence;
    }
    ownAssertFailureHandler("Negative number passed to createSequence()"s);
    // return std::vector<int>{}; //< Not needed because of [[noreturn]]
}

함수가 실제로 반환하면 정의되지 않은 동작이므로 다음은 허용되지 않습니다.

[[noreturn]] void assertPositive(int number) {
    if (number >= 0)
        return;
    else
        ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}

[[noreturn]] 은 대부분 void 함수에서 사용된다는 점에 유의하십시오. 그러나 이것은 요구 사항이 아니기 때문에 일반 프로그래밍에서 함수를 사용할 수 있습니다.

template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
    if (i == 0)
         i = InconsistencyHandler::correct(i);
    return 42. / i;
}

struct InconsistencyThrower {
    static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown inconsistency"s); }
}

struct InconsistencyChangeToOne {
    static int correct(int i) { return 1; }
}

double fortyTwo = fortyTwoDivideBy<InconsistencyChangeToOne>(0);
double unreachable = fortyTwoDivideBy<InconsistencyThrower>(0);

다음 표준 라이브러리 함수에는이 특성이 있습니다.

  • std :: abort
  • std :: exit
  • std :: quick_exit
  • std :: unexpected
  • std :: terminate
  • std :: rethrow_exception
  • std :: throw_with_nested
  • std :: nested_exception :: rethrow_nested

[[실패로 끝나다]]

C ++ 17

switch 에서 case 가 끝날 때마다 다음 케이스의 코드가 실행됩니다. 이 마지막 명령은 'break` 문을 사용하여 방지 할 수 있습니다. 이 소위 폴스 스루 동작으로 인해 의도하지 않은 버그가 발생할 수 있으므로 여러 컴파일러와 정적 분석기가 이에 대해 경고합니다.

C ++ 17에서 코드가 넘어 질 때 경고가 필요 없다는 것을 나타내는 표준 속성이 도입되었습니다. 컴파일러는 break 이나 [[fallthrough]] 없이 끝나고 적어도 하나의 명령문이있을 때 경고를 안전하게 줄 수 있습니다.

switch(input) {
    case 2011:
    case 2014:
    case 2017:
        std::cout << "Using modern C++" << std::endl;
        [[fallthrough]]; // > No warning
    case 1998:
    case 2003:
        standard = input;
}

[[fallthrough]] 어떻게 사용될 수 있는지에 대한보다 자세한 예제 는 제안서 를 참조하십시오.

[[deprecated]]와 [[deprecated ( "reason")]]

C ++ 14

C ++ 14에서는 속성을 통해 함수를 비추천 표준화하는 방법을 도입했습니다. [[deprecated]] 는 함수가 더 이상 사용되지 않음을 나타 내기 위해 사용될 수 있습니다. [[deprecated("reason")]] 컴파일러가 표시 할 수있는 특정 이유를 추가 할 수 있습니다.

void function(std::unique_ptr<A> &&a);

// Provides specific message which helps other programmers fixing there code
[[deprecated("Use the variant with unique_ptr instead, this function will be removed in the next release")]]
void function(std::auto_ptr<A> a);

// No message, will result in generic warning if called.
[[deprecated]]
void function(A *a);

이 속성은 다음에 적용될 수 있습니다.

  • 수업의 선언
  • typedef 이름
  • 변수
  • 비 정적 데이터 멤버
  • 함수
  • 열거
  • 템플릿 전문화

(참조 c ++ 14 표준 초안 : 7.6.5 사용되지 않는 속성)

[[nodiscard]]

C ++ 17

[[nodiscard]] 속성은 함수 호출을 할 때 함수의 반환 값이 무시되어서는 안된다는 것을 나타내는 데 사용할 수 있습니다. 반환 값이 무시되면 컴파일러에서 이에 대한 경고를 제공해야합니다. 속성을 다음에 추가 할 수 있습니다.

  • 함수 정의
  • 유형

유형에 속성을 추가하는 것은이 유형을 리턴하는 모든 단일 함수에 속성을 추가하는 것과 동일한 작동을합니다.

template<typename Function>
[[nodiscard]] Finally<std::decay_t<Function>> onExit(Function &&f);

void f(int &i) {
    assert(i == 0);                    // Just to make comments clear!
    ++i;                               // i == 1
    auto exit1 = onExit([&i]{ --i; }); // Reduce by 1 on exiting f()
    ++i;                               // i == 2
    onExit([&i]{ --i; });              // BUG: Reducing by 1 directly
                                       //      Compiler warning expected
    std::cout << i << std::end;        // Expected: 2, Real: 1
}

[[nodiscard]] 를 어떻게 사용할 수 있는지에 대한 자세한 예제 는 제안서 를 참조하십시오.

참고 : Finally / onExit 의 구현 세부 정보는 예제에서 생략됩니다 ( Finally / ScopeExit 참조).

[[maybe_unused]]

[[maybe_unused]] 속성은 코드에서 특정 논리가 사용되지 않을 수도 있음을 나타 내기 위해 만들어집니다. 이것은 자주 사용되거나 사용되지 않을 수도있는 선처리 조건에 링크되는 경우에 사용됩니다. 컴파일러는 사용되지 않는 변수에 대해 경고를 줄 수 있기 때문에 의도를 나타내어 컴파일러를 억제 할 수 있습니다.

프로덕션에서 불필요한 동안 디버그 빌드에 필요한 변수의 전형적인 예는 성공을 나타내는 리턴 값입니다. 디버그 빌드에서 조건은 어설 션되어야하지만 프로덕션에서는 이러한 어설 션이 제거되었습니다.

[[maybe_unused]] auto mapInsertResult = configuration.emplace("LicenseInfo", stringifiedLicenseInfo);
assert(mapInsertResult.second); // We only get called during startup, so we can't be in the map

더 복잡한 예제는 이름없는 네임 스페이스에있는 다른 종류의 도우미 함수입니다. 컴파일하는 동안이 함수를 사용하지 않으면 컴파일러에서 경고를 줄 수 있습니다. 이상적으로 호출자와 동일한 선행 처리기 태그를 사용하여이를 [[maybe_unused]] 는 것이 [[maybe_unused]] 그러나 이것이 복잡해 [[maybe_unused]] 때문에 [[maybe_unused]] 속성은 더 유지하기 [[maybe_unused]] 대안입니다.

namespace {
    [[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath);
    // TODO: Reuse this on BSD, MAC ...
    [[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath);
}

std::string createConfigFilePath(const std::string &relativePath) {
#if OS == "WINDOWS"
      return createWindowsConfigFilePath(relativePath);
#elif OS == "LINUX"
      return createLinuxConfigFilePath(relativePath);
#else
#error "OS is not yet supported"
#endif
}

[[maybe_unused]] 사용할 수있는 방법에 대한 자세한 예제 는 제안서 를 참조하십시오.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow