static_assert는 무엇을하고 무엇을 사용 하시겠습니까?
-
22-07-2019 - |
문제
당신은 어디에 예를 들여 줄 수 있습니까? static_assert(...) 'C++0x'
우아하게 문제를 해결할 수 있습니까?
런타임에 익숙합니다 assert(...)
. 언제 선호해야합니까? static_assert(...)
정기적으로 assert(...)
?
또한, boost
무언가가 있습니다 BOOST_STATIC_ASSERT
, 그것은 동일합니다 static_assert(...)
?
해결책
내 머리 꼭대기에서 ...
#include "SomeLibrary.h"
static_assert(SomeLibrary::Version > 2,
"Old versions of SomeLibrary are missing the foo functionality. Cannot proceed!");
class UsingSomeLibrary {
// ...
};
그것을 가정합니다 SomeLibrary::Version
존재하기보다는 정적 콘트로로 선언됩니다. #define
D (C ++ 라이브러리에서 기대할 수있는대로).
실제로 컴파일 해야하는 것과는 대조적입니다 SomeLibrary
그리고 코드, 모든 것을 연결하고 실행 파일 만 실행하십시오. 그 다음에 호환되지 않는 버전을 컴파일하는 데 30 분을 보냈다는 것을 알기 위해 SomeLibrary
.
@arak, 귀하의 의견에 대한 응답으로 : 예, static_assert
그 모습에서 어디서나 앉아 있습니다.
class Foo
{
public:
static const int bar = 3;
};
static_assert(Foo::bar > 4, "Foo::bar is too small :(");
int main()
{
return Foo::bar;
}
$ g++ --std=c++0x a.cpp a.cpp:7: error: static assertion failed: "Foo::bar is too small :("
다른 팁
정적 인제는 컴파일 시간에 주장을하는 데 사용됩니다. 정적 어설 션이 실패하면 프로그램은 단순히 컴파일하지 않습니다. 예를 들어, 코드별로 일부 기능을 구현하는 경우와 같이 다른 상황에서 유용합니다. unsigned int
정확히 32 비트를 가진 물체. 당신은 이와 같은 정적 인제를 넣을 수 있습니다
static_assert(sizeof(unsigned int) * CHAR_BIT == 32);
코드에서. 다른 크기의 다른 플랫폼에서 unsigned int
컴파일을 입력하면 실패하므로 개발자가 코드의 문제가있는 부분에주의를 기울이고 재 구현하거나 다시 확인하도록 조언합니다.
다른 예를 들어, 당신은 몇 가지 필수 값을 void *
함수에 대한 포인터 (해킹이지만 때때로 유용함) 및 적분 값이 포인터에 맞는지 확인하려고합니다.
int i;
static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);
당신은 그것을 자산하고 싶을 수도 있습니다 char
유형이 서명되었습니다
static_assert(CHAR_MIN < 0);
또는 음수 값을 가진 그 적분 분할이 0으로 향합니다.
static_assert(-5 / 2 == -2);
등등.
많은 경우에 런타임 어설 션은 정적 어설 션 대신에 사용할 수 있지만 런타임 어설 션은 런타임과 제어가 어설 션을 통과 할 때만 작동합니다. 이러한 이유로 실패한 런타임 주장은 휴면 상태가 될 수 있으며, 장기간 동안 감지되지 않을 수 있습니다.
물론, 정적 주장의 표현은 컴파일 타임 상수 여야합니다. 런타임 가치가 될 수는 없습니다. 런타임 값의 경우 다른 선택은 없지만 평범한 것을 사용하십시오. assert
.
컴파일러 동작, 헤더, 라이브 및 내 코드에 대한 가정이 올바른지 확인하기 위해 사용합니다. 예를 들어 여기서 구조물이 예상 크기로 올바르게 포장되었는지 확인합니다.
struct LogicalBlockAddress
{
#pragma pack(push, 1)
Uint32 logicalBlockNumber;
Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);
클래스 포장에서 stdio.h
'에스 fseek()
, 나는 바로 가기를 가져 갔다 enum Origin
그리고 그 바로 가기가 stdio.h
uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);
당신은 선호해야합니다 static_assert
~ 위에 assert
동작이 컴파일 타임에 정의 된 경우, 위에서 제시 한 예제와 같이 런타임이 아니라. 이것이 어디에 있는가 ~ 아니다 이 사례에는 매개 변수 및 반환 코드 확인이 포함됩니다.
BOOST_STATIC_ASSERT
조건이 충족되지 않은 경우 불법 코드를 생성하는 사전 C ++ 0X 매크로입니다. 의도는 동일하지만 동일합니다 static_assert
표준화되며 더 나은 컴파일러 진단을 제공 할 수 있습니다.
BOOST_STATIC_ASSERT
크로스 플랫폼 래퍼입니다 static_assert
기능.
현재 수업에서 "개념"을 시행하기 위해 static_assert를 사용하고 있습니다.
예시:
template <typename T, typename U>
struct Type
{
BOOST_STATIC_ASSERT(boost::is_base_of<T, Interface>::value);
BOOST_STATIC_ASSERT(std::numeric_limits<U>::is_integer);
/* ... more code ... */
};
위의 조건 중 하나가 충족되지 않으면 컴파일 시간 오류가 발생합니다.
하나의 사용 static_assert
구조 (네트워크 또는 파일과 같은 외부 세계와의 인터페이스)가 정확히 예상되는 크기인지 확인하는 것일 수 있습니다. 이것은 누군가가 결과를 실현하지 않고 구조에서 구성원을 추가하거나 수정하는 경우를 포착 할 것입니다. 그만큼 static_assert
그것을 집어 들고 사용자에게 경고합니다.
개념이 없으면 사용할 수 있습니다 static_assert
예를 들어 템플릿에서 간단하고 읽기 쉬운 컴파일 타임 유형 확인의 경우 :
template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value,
"T must be derived from MyBase");
// ...
}
이것은 원래 질문에 직접적인 답변을받지는 않지만 C ++ 11 이전에 이러한 컴파일 시간 검사를 시행하는 방법에 대한 흥미로운 연구를합니다.
2 장 (섹션 2.1) 현대 C ++ 디자인 작성자 : Andrei Alexanderscu는 이와 같은 컴파일 타임 어설
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
Macro static_check () 및 static_assert () 비교
STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");