static_assert의 기능은 무엇이며 어떤 용도로 사용 하시겠습니까?
static_assert(...)
( 'C ++ 11')이 문제를 우아하게 해결할 수있는 예를 들어 주 시겠습니까?
나는 사용에 익숙하다 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 {
// ...
};
그것이 C SomeLibrary::Version
가 아닌 정적 const로 선언 가정하면 #define
(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 : 오류 : 정적 어설 션이 실패했습니다 : "Foo :: bar가 너무 작습니다 :("
정적 어설 션은 만드는 타임에 어설 션을 만드는 데 사용됩니다. 정적 어설 션이 실패하면 프로그램은 없습니다. 이는 동일한 예를 들어 unsigned int
정확히 32 비트를 가진 기능에 크게 의존하는 코드로 일부를 구현하는 경우에 유용합니다 . 이런 식으로 정적 assert를 넣을 수 있습니다.
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 이전에 이러한 컴파일 시간 검사를 시행하는 방법에 대한 흥미로운 연구를 만듭니다.
Andrei Alexanderscu 의 Modern C ++ Design 2 장 (섹션 2.1)은 다음과 같은 컴파일 타임 어설 션 아이디어를 구현합니다.
template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};
#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; }
매크로 STATIC_CHECK () 및 static_assert () 비교
STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");
는 다음과 같은 방식으로 키워드 static_assert
사용을 금지하는 데 사용할 수 있습니다 delete
.
#define delete static_assert(0, "The keyword \"delete\" is forbidden.");
모든 최신 C ++ 개발자는 보수적 가비지 수집기 의 보수적 힙에 메모리를 할당하는 함수를 호출하기 위해 new 연산자 를 오버로드하는 클래스 es 및 struct 를 사용하여 보수적 가비지 수집기를 사용하려는 경우이를 수행 할 수 있습니다. 함수의 시작 부분에서이를 수행하는 일부 함수를 호출하여 초기화 및 인스턴스화 할 수 있습니다 .main
예를 들어 Boehm-Demers-Weiser 보수적 가비지 수집기를 사용하려는 모든 최신 C ++ 개발자는 main
함수 시작 부분에 다음과 같이 작성합니다.
GC_init();
그리고 모든 년 class
및 struct
과부하 operator new
이런 식으로 :
void* operator new(size_t size)
{
return GC_malloc(size);
}
그리고 이제는 operator delete
더 이상 필요하지 않습니다. Boehm-Demers-Weiser 보수적 가비지 수집기가 더 이상 필요하지 않을 때 모든 메모리 블록을 해제하고 할당 해제해야하기 때문에 개발자는 delete
키워드 를 금지하려고 합니다.
한 가지 방법은 다음과 같이 오버로드하는 delete operator
것입니다.
void operator delete(void* ptr)
{
assert(0);
}
그러나 이것은 권장되지 않습니다. 현대의 C ++ 개발자는 자신 delete operator
이 런타임에 실수로를 호출했음을 알 수 있기 때문에 컴파일 타임에 이것을 곧 아는 것이 좋습니다.
따라서이 시나리오에 대한 가장 좋은 해결책 static_assert
은이 답변의 시작 부분에 표시된 것처럼 사용하는 것입니다.
물론 이것은로도 할 수 BOOST_STATIC_ASSERT
있지만 나는 그것이 static_assert
더 낫고 항상 더 선호되어야 한다고 생각합니다 .
참고 URL : https://stackoverflow.com/questions/1647895/what-does-static-assert-do-and-what-would-you-use-it-for
'IT' 카테고리의 다른 글
두 개의 포인터 만 사용하여 단일 연결 목록을 뒤집는 방법은 무엇입니까? (0) | 2020.08.03 |
---|---|
불변은 무엇입니까? (0) | 2020.08.03 |
VIM 단어를 변조의 내용으로 바꾸시겠습니까? (0) | 2020.08.03 |
emacs는 ido를 활성화하여 새 파일을 만듭니다. (0) | 2020.08.03 |
phpinfo ()-그것을 볼 수있는 쉬운 방법이 있습니까? (0) | 2020.08.03 |