문제

C#에서는 일반 매개 변수로 사용할 수있는 유형에 제약 조건을 부과하는 일반 유형을 정의 할 수 있습니다. 다음 예는 일반적인 제약 조건을 보여줍니다.

interface IFoo
{
}


class Foo<T> where T : IFoo
{
}

class Bar : IFoo
{
}

class Simpson
{
}

class Program
{
    static void Main(string[] args)
    {
        Foo<Bar> a = new Foo<Bar>();
        Foo<Simpson> b = new Foo<Simpson>(); // error CS0309
    }
}

C ++에서 템플릿 매개 변수에 대한 제약 조건을 부과 할 수있는 방법이 있습니까?


C ++ 0X는 이에 대한 기본 지원을 가지고 있지만 현재 표준 C ++에 대해 이야기하고 있습니다.

도움이 되었습니까?

해결책

다른 사람이 언급했듯이 C ++ 0X는 이것을 언어로 내장하고 있습니다. 그때까지는 추천합니다 Bjarne Stroustrup'에스 템플릿 제약 조건에 대한 제안.

편집하다: 후원 또한 자신의 대안.

edit2 : C ++ 0x에서 개념이 제거되었습니다.

다른 팁

C ++ 11을 사용하는 경우 사용할 수 있습니다. static_assert ~와 함께 std::is_base_of 이 목적을 위해.

예를 들어,

#include <type_traits>

template<typename T>
class YourClass {

    YourClass() {
        // Compile-time check
        static_assert(std::is_base_of<BaseClass, T>::value, "type parameter of this class must derive from BaseClass");

        // ...
    }
}

"암시 적으로"는 정답입니다. 템플릿은 컴파일하는 방식으로 인해 "오리 타이핑"시나리오를 효과적으로 만듭니다. 템플릿 유형 값에서 원하는 함수를 호출 할 수 있으며, 허용되는 유일한 인스턴스화는 해당 메소드가 정의 된 것입니다. 예를 들어:

template <class T>
int compute_length(T *value)
{
    return value->length();
}

우리는이 메소드를 선언하는 모든 유형에 대한 포인터에서 호출 할 수 있습니다. length() 반환 방법 int. 따라서 :

string s = "test";
vector<int> vec;
int i = 0;

compute_length(&s);
compute_length(&vec);

...하지만 유형에 대한 포인터는 아닙니다. ~ 아니다 선언하다 length():

compute_length(&i);

이 세 번째 예제는 컴파일되지 않습니다.

C ++는 각 인스턴스화에 대해 새 버전의 템플릿 기능 (또는 클래스)을 컴파일하기 때문에 작동합니다. 그 컴파일을 수행함에 따라, 유형-점검 전에 템플릿 인스턴스화의 직접적이고 거의 거시적 인 대체를 코드로 대체합니다. 모든 것이 여전히 해당 템플릿으로 작동하면 컴파일이 진행되고 결국 결과에 도달합니다. 실패한 경우 (같은 int* 선언하지 않습니다 length()), 우리는 두려운 6 페이지 템플릿 컴파일 타임 오류를 얻습니다.

아무것도하지 않는 ifoo에 가드 유형을 넣을 수 있습니다. foo의 t에 있는지 확인하십시오.

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

template <typename T>
class Foo<T>
{
    typedef typename T::IsDerivedFromIFoo IFooGuard;
}

체크 아웃 후원

부스트 컨셉 체크 라이브러리 (BCCL)

개념 확인 라이브러리를 사용하면 명시 적 진술과 확인을 추가 할 수 있습니다. 개념 스타일로 제안 된 C ++ 언어 확장.

일종의. ifoo *에 static_cast가있는 경우 발신자가 ifoo *에 할당 할 수있는 클래스를 통과하지 않는 한 템플릿을 인스턴스화하는 것은 불가능합니다.

암시 적으로 만.
실제로 호출되는 메소드에서 사용하는 모든 메소드는 템플릿 매개 변수에 부과됩니다.

할 수 있어요. 기본 템플릿을 만듭니다. 개인 생성자 만 갖습니다. 그런 다음 허용하려는 각 케이스에 대한 전문화를 만듭니다 (또는 허용되지 않은 목록이 허용 목록보다 훨씬 작은 경우 반대).

컴파일러를 사용하면 개인 생성자와 함께 버전을 사용하는 템플릿을 인스턴스화 할 수 없습니다.

이 예제는 int 및 float와의 인스턴스화 만 허용합니다.

template<class t> class FOO { private: FOO(){}};

template<> class FOO<int>{public: FOO(){}};

template<> class FOO<float>{public: FOO(){}};

짧고 우아한 방법은 아니지만 가능합니다.

CRTP 패턴을보십시오 (호기심으로 재귀 템플릿 패턴). 정적 인물을 지원하도록 설계되었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top