2010-06-17 3 views
8

템플릿 클래스에 제한을 설정할 수있는 방법이 있습니까?
템플릿에서 대체 된 모든 유형에 특정 조상이 있어야 함을 지정합니다 (일부 인터페이스 실현). 하스켈C++ 템플릿 제한

func :: (Ord a, Show b) => a -> b -> c 
+1

왜 당신이 필요가 있다고 생각합니까? – fredoverflow

+0

가능한 [C++ 클래스 특정 기본 클래스 템플릿] (http://stackoverflow.com/questions/2012950/c-class-template-of-specific-baseclass) – SLaks

+1

sooooo 초보자 질문 :-). 개념은 실제로 꽤 논란의 여지가 있습니다. –

답변

2

당신은 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(); 
    } 
}; 
2

당신은이 같은 트릭을 사용할 수 있습니다 쓸 수 있습니다 :

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 
+0

이 코드는 g ++ 4.4에서 알 수없는 이유로 인해 실패하지 않습니다.일반적으로이 경우에는 열거 형이 일반적으로 사용됩니다. enum {TEMPLATE_REQUIRES_BASE_CLASS = 0}; g ++에서 예상대로 실패하는 추가 이점이 있습니다. – iksemyonov

+0

@Semen, GCC는 부적합합니다. 표준은 클래스가 암시 적으로 인스턴스화되고 클래스의 초기화자가 정의의 일부가 아닌 선언의 일부일 때 데이터 멤버의 선언을 인스턴스화 할 것을 요구합니다. 그러나 스탠다드는 약간 불명확하며 "정적 데이터 멤버의 정의가 요구되는 방식으로 정적 데이터 멤버 자체가 사용되지 않으면 정적 데이터 멤버의 초기화 (및 관련된 부작용)가 발생하지 않습니다. " -이 규칙은 클래스 밖 초기화 자에만 적용되는 것처럼 보입니다. (그렇지 않으면 별 의미가 없습니다.) –

+0

@Johannes : 설명 주셔서 감사합니다. 괜찮을 때 미쳐 가고 있다고 생각했지만 ... 열거 형은 여전히 사용하기 더 쉽다. (난 그냥 Vandervourde 다음과 같습니다 :) – iksemyonov

6

향후 버전 (C++ (11) 안으로 들어가지는 못했습니다)이 기본적으로 사용하는 개념을 지원합니다. 이 문제를 접근하는

한 가지 방법은 더미 템플릿 매개 변수에 전문화를 사용하는 것입니다 : 내가 enable_ifis_base_and_derivedhere의 독립형 정의를 넣었습니다

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> 

.

+0

감사합니다, 멋진 코드 조각 – Andrew

1

템플릿은 C++에서 오리 유형의 일종입니다.

클래스가 템플릿에서 사용하는 모든 것을 지원하면 템플릿 인수로 사용할 수 있습니다. 그렇지 않으면 템플릿에서 사용할 수 없습니다.

당신은 템플릿의 경우

C *instance; 

void foo(T *t) 
{ 
    instance = t; 
} 

당신은 T는 C (또는 적어도 assignement 호환 포인터에 대한) VC10에서

3

다음 작품 사용에서 파생되는 시행하고 같은 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>   ]