정적 데이터 구성원을 헤더 전용 라이브러리에 포함시키는 방법은 무엇입니까?
-
13-12-2019 - |
문제
비 템플릿 라이브러리 클래스에 정적 멤버를 갖는 가장 좋은 방법은 무엇입니까? 클래스 사용자의 멤버 정의의 부담을 배치하지 않고?
이 수업을 제공하고 싶습니다 :
class i_want_a_static_member
{
static expensive_resource static_resource_;
public:
void foo()
{
static_resource_.bar();
}
};
.
다음 클래스의 사용자는 어딘가에 정적 멤버를 정의하는 것을 잊지 않아야합니다. (이미 이미 답변 됨 많은 시간 ) :
// this must be done somewhere in a translation unit
expensive_resource i_want_a_static_member::static_resource_;
.
아래의 답변이 있지만 몇 가지 단점이 있습니다.더 나은 우아한 솔루션이 있고 더 우아한 솔루션이 있습니까?
해결책
C ++ 17 이상
비 동적 초기화를 위해 inline static
변수를 사용합니다.
struct Foo
{
inline static int I = 0;
};
.
및 사용 함수 로컬 정적 변수는 그렇지 않으면 다음과 같습니다.
struct Foo
{
static std::string& Bar()
{
static std::string S = compute();
return S;
}
};
.
C ++ 14 및 아래
함수 로컬 statics를 사용하면 사용할 수 없으므로
어떤 이유로 정적 데이터 멤버 에 대해 실제로 원하는 경우 템플릿 트릭을 사용할 수 있습니다 :
template <typename T = void>
struct Foo
{
static int I = 0; // inline initialization only for simple types.
};
template <typename T>
int Foo<T>::I;
.
로컬 통계
동적 초기화가 필요한 자원에 대해서는 로컬 정적을 사용하는 것이 가장 좋습니다.
파일 범위 또는 클래스 범위 statics가 동적으로 초기화되는 순서는 일반적으로 다른 사람의 초기화의 일부로 초기화되지 않은 정전기를 읽으려고 할 때 정적 초기화 순서로 이어집니다. 로컬 정적 첫 번째 사용시 초기화 된 Lazily로 문제를 해결하십시오.
로컬 통계를 사용하는 데 약간의 오버 헤드가 있습니다. C ++ 11에서 초기화는 스레드 안전성이어야합니다. 일반적으로 원자 읽기 및 잘 예측 된 지점에 의해 모든 액세스가 게이트 된 경우
다른 팁
내 솔루션은 정적 멤버가 템플릿에서 잘 작동 하므로이 홀더를 기본 클래스로 사용하는 것처럼 템플릿 홀더 클래스를 사용하는 것입니다.
template <typename T>
struct static_holder
{
static T static_resource_;
};
template <typename T>
T static_holder<T>::static_resource_;
.
이제 홀더 클래스를 사용합니다.
class expensive_resource { /*...*/ };
class i_want_a_static_member : private static_holder<expensive_resource>
{
public:
void foo()
{
static_resource_.bar();
}
};
.
그러나 홀더 클래스에 구성원의 이름이 지정되면 둘 이상의 정적 멤버에 대해 동일한 홀더를 사용할 수 없습니다.
C ++ 17. 이제 인라인 변수를 사용하여 다음을 수행 할 수 있습니다.
static const inline float foo = 1.25f;
.