템플릿 클래스에 제한을 설정할 수있는 방법이 있습니까?
템플릿에서 대체 된 모든 유형에 특정 조상이 있어야 함을 지정합니다 (일부 인터페이스 실현). 하스켈C++ 템플릿 제한
func :: (Ord a, Show b) => a -> b -> c
템플릿 클래스에 제한을 설정할 수있는 방법이 있습니까?
템플릿에서 대체 된 모든 유형에 특정 조상이 있어야 함을 지정합니다 (일부 인터페이스 실현). 하스켈C++ 템플릿 제한
func :: (Ord a, Show b) => a -> b -> c
당신은 use BOOST_STATIC_ASSERT
또는 유사한 라이브러리가 템플릿 매개 변수에 대한 당신의 제한을 주장 할 수있는 =처럼
template < class B > //and every B must be a child of abstract C
class A {
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
>.
#include <limits>
#include <boost/static_assert.hpp>
template <class UnsignedInt>
class myclass
{
private:
BOOST_STATIC_ASSERT((std::numeric_limits<UnsignedInt>::digits >= 16)
&& std::numeric_limits<UnsignedInt>::is_specialized
&& std::numeric_limits<UnsignedInt>::is_integer
&& !std::numeric_limits<UnsignedInt>::is_signed);
public:
/* details here */
};
편집 : 예를 들어
귀하의 예를 들어, 당신이 (당신이 부스트를 사용하지 않는 경우)
template < class B >
class A {
BOOST_STATIC_ASSERT(boost::is_base_of<C, B>);
public:
B * obj;
int f() {
return B::x + this->obj->f();
}
};
당신은이 같은 트릭을 사용할 수 있습니다 쓸 수 있습니다 :
class Base
{
public:
static const int TEMPLATE_REQUIRES_BASE_CLASS = 0;
};
class Correct : public Base
{
};
class Incorrect
{
};
template <typename T>
class TMPL
{
static const int TEMPLATE_REQUIRES_BASE_CLASS = T::TEMPLATE_REQUIRES_BASE_CLASS;
T *m_t;
};
void main()
{
TMPL<Correct> one; // OK
TMPL<Incorrect> two; // Will not compile
}
첫 번째 줄이 컴파일됩니다. 두 번째는 컴파일되지 않고 다음과 같은 오류를 줄 것이다 : C++의
test.cpp
test.cpp(18) : error C2039: 'TEMPLATE_REQUIRES_BASE_CLASS' : is not a member of 'Incorrect'
test.cpp(12) : see declaration of 'Incorrect'
test.cpp(25) : see reference to class template instantiation 'TMPL<T>' being compiled
with
[
T=Incorrect
]
test.cpp(18) : error C2065: 'TEMPLATE_REQUIRES_BASE_CLASS' : undeclared identifier
test.cpp(18) : error C2057: expected constant expression
이 코드는 g ++ 4.4에서 알 수없는 이유로 인해 실패하지 않습니다.일반적으로이 경우에는 열거 형이 일반적으로 사용됩니다. enum {TEMPLATE_REQUIRES_BASE_CLASS = 0}; g ++에서 예상대로 실패하는 추가 이점이 있습니다. – iksemyonov
@Semen, GCC는 부적합합니다. 표준은 클래스가 암시 적으로 인스턴스화되고 클래스의 초기화자가 정의의 일부가 아닌 선언의 일부일 때 데이터 멤버의 선언을 인스턴스화 할 것을 요구합니다. 그러나 스탠다드는 약간 불명확하며 "정적 데이터 멤버의 정의가 요구되는 방식으로 정적 데이터 멤버 자체가 사용되지 않으면 정적 데이터 멤버의 초기화 (및 관련된 부작용)가 발생하지 않습니다. " -이 규칙은 클래스 밖 초기화 자에만 적용되는 것처럼 보입니다. (그렇지 않으면 별 의미가 없습니다.) –
@Johannes : 설명 주셔서 감사합니다. 괜찮을 때 미쳐 가고 있다고 생각했지만 ... 열거 형은 여전히 사용하기 더 쉽다. (난 그냥 Vandervourde 다음과 같습니다 :) – iksemyonov
향후 버전 (C++ (11) 안으로 들어가지는 못했습니다)이 기본적으로 사용하는 개념을 지원합니다. 이 문제를 접근하는
한 가지 방법은 더미 템플릿 매개 변수에 전문화를 사용하는 것입니다 : 내가 enable_if
과 is_base_and_derived
here의 독립형 정의를 넣었습니다
class C {};
template <class B, class dummy=void>
class A;
template <class B>
class A<B, typename enable_if<is_base_and_derived<C, B> >::type>
{
// class definition here
};
struct D : C {};
A<D> d; // fine
A<int> n; // compile error - undefined class A<B>
.
감사합니다, 멋진 코드 조각 – Andrew
템플릿은 C++에서 오리 유형의 일종입니다.
클래스가 템플릿에서 사용하는 모든 것을 지원하면 템플릿 인수로 사용할 수 있습니다. 그렇지 않으면 템플릿에서 사용할 수 없습니다.
당신은 템플릿의 경우
C *instance;
void foo(T *t)
{
instance = t;
}
당신은 T는 C (또는 적어도 assignement 호환 포인터에 대한) VC10에서
다음 작품 사용에서 파생되는 시행하고 같은 static_assert. 나는 이것을 사용한 것을 보았고 실제로 static_assert가 실제로하는 일을별로 신경 쓰지 않았습니다. 아마 다른 누군가가 대답 할 수 있습니다.
#include <type_traits>
class Base
{
};
class Derived : public Base
{
};
class SomeRandomClass
{
};
template<typename T>
class A
{
static_assert(std::tr1::is_base_of<Base, T>::value, "T not derived from Base");
};
int _tmain(int argc, _TCHAR* argv[])
{
argc; argv;
//
// This will compile
A<Derived> a;
//
// This will throw a compilation error
A<SomeRandomClass> b;
return 0;
}
는 컴파일러 출력 존재 :
1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1> d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1> with
1> [
1> T=SomeRandomClass
1> ]
왜 당신이 필요가 있다고 생각합니까? – fredoverflow
가능한 [C++ 클래스 특정 기본 클래스 템플릿] (http://stackoverflow.com/questions/2012950/c-class-template-of-specific-baseclass) – SLaks
sooooo 초보자 질문 :-). 개념은 실제로 꽤 논란의 여지가 있습니다. –