C++20을 사용해 봅시다 | std::is_constant_evaluated()
std::is_constant_evaluated()
는 C++20의 많은 새로운 작은 기능 중 하나입니다. Specified in P0595R2
, 이 기능은 <type_traits>
헤더에서 사용할 수 있습니다. 다음은 cppreference의 설명입니다.
constexpr bool is_constant_evaluated() noexcept;
Detects whether the function call occurs within a constant-evaluated context. Returns
true
if the evaluation of the call occurs within the evaluation of an expression or conversion that is manifestly constant-evaluated; otherwise returnsfalse
.
이것은 꽤 간단하게 들립니다.
constexpr 함수의 이점
이것은
constexpr
함수에 대해 매우 흥미로울 수 있습니다. constexpr
함수가 실제로 컴파일 타임에 실행된다는 보장이 없다는 것을 알고 있을 것입니다. 이것은 함수가 호출되는 방식에 따라 다릅니다.constexpr int foo() {
return 0;
}
constexpr auto a = foo(); // compile-time executed
auto b = foo(); // runtime executed (*)
(*) : 사실, 함수가 런타임에 평가된다는 보장은 없습니다. 함수의 내용, 변수의 범위, 최적화 수준 또는 기타 요인에 따라 컴파일러는 컴파일 타임에 평가할 수 있습니다
b
.때로는 함수가 컴파일 타임이든 런타임 실행이든 다르게 동작하고 싶을 수 있습니다.
std::is_constant_evaluated()
를 사용하면 이제 다음이 가능합니다.constexpr int foo() {
if (std::is_constant_evaluated()) {
return 0;
} else {
std::cout << "at runtime\n";
return 1;
}
}
컨텍스트에 따라
foo()
는 0 또는 1을 반환합니다. 위에서 언급한 대로 놀랄 수 있습니다. 예를 들어 clang 11.0.0을 사용하는 경우 다음 코드는 1을 반환합니다.int a = foo();
int main() {
int b = foo();
return a + b;
}
실제로
a
는 상수 평가됩니다. 분명히 a
에는 정적 저장 기간이 있고 (b
에는 자동 저장 기간이 있음) 이것이 "is another context that might be evaluated at compile time [...] and this too interacts with std::is_constant_evaluated."이기 때문입니다.비 constexpr 함수에서
std::is_constant_evaluated()
의 용법은 constexpr
함수에서만 해당되는 것으로 밝혀졌다. stackoverlow: "C++20 | std::is_constant_evaluated() and const variables" 에 대한 이 토론을 참조하십시오.예를 들어,
const
변수(상수 평가 컨텍스트로 간주되지 않음, P0595R2의 "호출 (3)"참조) 또는 consteval
함수를 초기화하기 위해 일반 함수에서 이를 사용하는 것은 무의미합니다. (확실히 상수 평가 컨텍스트에서 호출됨).제안서에는 다음과 같이 명시되어 있습니다.
The standard doesn't actually make a distinction between "compile time" and "run time", and hence a more careful specification is needed, one that fits the standard framework of "constant expressions".
Our approach is to precisely identify a set of expressions that are "manifestly constant-evaluated" (a new technical phrase) and specify that our new function returns true during the evaluation of such expressions and false otherwise.
이것이 cppreference가 "컴파일 타임 컨텍스트"가 아닌 "상수 평가 컨텍스트"를 사용하는 이유입니다.
명백한 경우의 경고
cppreference에 따르면:
When directly used as the condition of
static_assert
declaration orconstexpr if
statement, std::is_constant_evaluated()always returns
true`.
이러한 경우 컴파일러에서 경고를 받을 수 있습니다.
소리와 함께:
bash
warning: 'std::is_constant_evaluated' will always evaluate to 'true' in a manifestly constant-evaluated expression [-Wconstant-evaluated]
With gcc (if you add the option -Wall
):
cpp
warning: 'std::is_constant_evaluated' always evaluates to true in 'if constexpr' [-Wtautological-compare]
결론
std::is_constant_evaluated()
는 constexpr
함수에서 컴파일 시간 친화적 알고리즘을 선택하는 좋은 방법입니다. 온전함의 안전한 가장자리를 유지하고 내 예에서와 같이 함수의 동작을 완전히 변경하는 데 사용하지 마십시오 😉
Reference
이 문제에 관하여(C++20을 사용해 봅시다 | std::is_constant_evaluated()), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/pgradot/let-s-try-c-20-std-isconstantevaluated-34pb텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)