두 템플릿으로 제공되는 템플릿 클래스 Foo
이 있습니다. 템플릿 템플릿 매개 변수는 두 가지가 있습니다. 클래스에 멤버 변수를 저장하고 getter 및 setter를 제공하기 위해 클래스에 몇 가지 추가 기능이 필요합니다. 또한 추가 유형에 대해 추가 static_assert()
을 수행해야하며 일반 생성자를 비활성화하고 해당 유형의 매개 변수도 제공해야합니다. 다음과 같이 보입니다 :상속 또는 클래스 특수화를 사용하지 않고 멤버 함수 및 변수를 사용하지 않습니다.
template <class Irrelevant, class Extra>
class Foo {
//other stuff...
static_assert(is_good_v<Extra>);
Extra extra;
public:
//other stuff...
Foo(Irrelevant i) {/* irrelevant */}
//now methods I need to enable only when Extra is present
Foo(Irrelevant i, Extra e) : extra(e) {/* irrelevant */}
void setExtra(Extra e) {extra = e;}
void getExtra() {return extra;}
};
나는 여러 가지 접근법을 시도했지만 아무 것도 만족스럽지 못했습니다. 우선 상속 사용하려고 :
template <class Irrelevant>
class Bar {
//other stuff...
public:
//other stuff...
Foo(Irrelevant i) {/* irrelevant */}
};
template <class Irrelevant, class Extra>
class Foo : public Bar<Irrelevant> {
static_assert(is_good_v<Extra>);
Extra extra;
public:
Foo(Irrelevant i, Extra e) : Bar<Irrelevant>(i), extra(e) {/* irrelevant */}
void setExtra(Extra e) {extra = e;}
void getExtra() {return extra;}
};
template <class Irrelevant>
class Foo : public Bar<Irrelevant> {};
이 (유사하거나 뭔가 이상)이 혼자 일을하지만, 다른 곳에서 그들에 템플릿 검사를 수행 할 때 별도의 해결을 요구, 또한 '는 불필요 글로벌 네임 스페이스를 산재 나는 shouldn 그렇게하는거야. 두 번째 방법은 다음과 같이, Foo
의 전문성을했다 :
template <class Irrelevant, class... T>
class Foo {};
template <class Irrelevant, class Extra>
class Foo<Irrelevant, Extra> {
//other stuff...
static_assert(is_good_v<Extra>);
Extra extra;
public:
//other stuff...
Foo(Irrelevant i) {/* irrelevant */}
//now methods I need to enable only when Extra is present
Foo(Irrelevant i, Extra e) : extra(e) {/* irrelevant */}
void setExtra(Extra e) {extra = e;}
void getExtra() {return extra;}
};
template <class Irrelevant>
class Foo<Irrelevant> {
//other stuff...
public:
//other stuff...
Foo(Irrelevant i) {/* irrelevant */}
};
그리고 이것은 또한 일을하고, 쓰레기 글로벌 네임 스페이스를하지 않았다, 그러나 //other stuff
모든 위대한하지 않은, 중복되었다. 시도하고 싶었던 세 번째 접근법은 std::enable_if
모든 것들 이었지만 작동시키지 못했습니다. 나는이 같은 시도 :
template <class Irrelevant, class Extra = void>
class Foo {
//other stuff...
static constexpr bool hasExtra = std::is_same_v<Extra, void>;
static_assert(!hasExtra || is_good_v<Extra>);
std::conditional<hasExtra, Extra, bool> extra;
public:
//other stuff...
template <typename = typename std::enable_if_t<!hasExtra>>
Foo(Irrelevant i) {/* irrelevant */}
//now methods I need to enable only when Extra is present
template <typename = typename std::enable_if_t<hasExtra>>
Foo(Irrelevant i, Extra e) : extra(e) {/* irrelevant */}
template <typename = typename std::enable_if_t<hasExtra>>
void setExtra(Extra e) {extra = e;}
template <typename = typename std::enable_if_t<hasExtra>>
void getExtra() {return extra;}
};
을하지만 SFINAE은 그것의 방법을 SFINAE하는 다른 기능이 없기 때문에이 getter 및 setter를 컴파일 할 때에 컴파일 오류가 발생하기 때문에이 분명 작동하지 않습니다. 그리고 Extra == void
에 대한 더미 함수를 추가하면 누군가 해당 함수를 사용하는 코드가 컴파일됩니다. 어떻게 제대로 할 수 있습니까?
같은 것을 당신이 _mixins_ 오히려 [CRTP (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)를 사용이 필요합니다. – user0042
필자는 쓴대로 Foo를 제외한 모든 이름을 전역 이름 공간에 추가하지 않기를 원합니다. – Joald
글로벌 네임 스페이스에서 믹스 인 클래스를 어떻게 강제 적용 할 수 있습니까? 오직 간접적 인 계층과'enable_if()'를 필요에 따라 추가하십시오. – user0042