수색…
통사론
[[details]] : 단순한 인수없는 속성
[[details (arguments)]] : 인수가있는 속성
__attribute (세부 정보) : 비표준 GCC / Clang / IBM 특정
__declspec (세부 정보) : 비표준 MSVC 관련
[[noreturn]]
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
[[실패로 끝나다]]
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에서는 속성을 통해 함수를 비추천 표준화하는 방법을 도입했습니다. [[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]]
[[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]]
사용할 수있는 방법에 대한 자세한 예제 는 제안서 를 참조하십시오.