C ++ 템플릿 매개 변수를 하위 클래스로 제한 변수 T를 특정 클래스의 하위

템플릿 매개 변수 T를 특정 클래스의 하위 클래스로 지정하려면 Baseclass어떻게해야합니까? 이 같은:

template <class T : Baseclass> void function(){
    T *object = new T();

}



답변

이 경우 다음을 수행 할 수 있습니다.

template <class T> void function(){
    Baseclass *object = new T();

}

T가 Baseclass의 서브 클래스가 아니면 (또는 T Baseclass) 컴파일되지 않습니다 .


답변

C ++ 11 호환 컴파일러를 사용하면 다음과 같이 할 수 있습니다.

template<class Derived> class MyClass {

    MyClass() {
        // Compile-time sanity check
        static_assert(std::is_base_of<BaseClass, Derived>::value, "Derived not derived from BaseClass");

        // Do other construction related stuff...
        ...
   }
}

CYGWIN 환경에서 gcc 4.8.1 컴파일러를 사용하여 이것을 테스트 했으므로 * nix 환경에서도 작동해야합니다.


답변

런타임에 덜 쓸모없는 코드를 실행하려면 다음을 참조하십시오 .
http://www.stroustrup.com/bs_faq2.html#constraints
는 컴파일 시간 테스트를 효율적으로 수행하고 더 좋은 오류 메시지를 생성하는 일부 클래스를 제공합니다.

특히:

template<class T, class B> struct Derived_from {
        static void constraints(T* p) { B* pb = p; }
        Derived_from() { void(*p)(T*) = constraints; }
};

template<class T> void function() {
    Derived_from<T,Baseclass>();
}


답변

개념은 필요하지 않지만 SFINAE를 사용할 수 있습니다.

template <typename T>
boost::enable_if< boost::is_base_of<Base,T>::value >::type function() {
   // This function will only be considered by the compiler if
   // T actualy derived from Base
}

이는 조건이 충족 될 때만 함수를 인스턴스화하지만 조건이 충족되지 않으면 현명한 오류를 제공하지 않습니다.


답변

C ++ 11부터 Boost 또는 static_assert. C ++ 11은 is_base_ofenable_if. C ++ 14에는 편의 유형이 도입 enable_if_t되었지만 C ++ 11을 사용 enable_if::type하는 경우 간단히 대신 사용할 수 있습니다 .

대안 1

David Rodríguez 의 솔루션은 다음과 같이 다시 작성할 수 있습니다.

#include <type_traits>

using namespace std;

template <typename T>
enable_if_t<is_base_of<Base, T>::value, void> function() {
   // This function will only be considered by the compiler if
   // T actualy derived from Base
}

대안 2

C ++ 17부터 is_base_of_v. 솔루션은 다음과 같이 다시 작성할 수 있습니다.

#include <type_traits>

using namespace std;

template <typename T>
enable_if_t<is_base_of_v<Base, T>, void> function() {
   // This function will only be considered by the compiler if
   // T actualy derived from Base
}

대안 3

전체 템플릿을 제한 할 수도 있습니다. 이 방법을 사용하여 전체 클래스를 정의 할 수 있습니다. 의 두 번째 매개 변수가 어떻게 enable_if_t제거되었는지 확인하십시오 (이전에 void로 설정 됨). 기본값은 실제로 void이지만 사용하지 않기 때문에 중요하지 않습니다.

#include <type_traits>

using namespace std;

template <typename T,
          typename = enable_if_t<is_base_of_v<Base, T>>>
void function() {
   // This function will only be considered by the compiler if
   // T actualy derived from Base
}

로부터 문서 템플릿 매개 변수의, 우리는 그 볼 typename = enable_if_t...빈 이름을 가진 템플릿 매개 변수입니다. 우리는 단순히 타입의 정의가 존재하는지 확인하기 위해 그것을 사용하고 있습니다. 특히 는의 밑이 아닌 enable_if_t경우 정의 Base되지 않습니다 T.

위의 기술은 enable_if.


답변

당신이 사용할 수있는 부스트 개념 확인 ‘들 BOOST_CONCEPT_REQUIRES:

#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>

template <class T>
BOOST_CONCEPT_REQUIRES(
    ((boost::Convertible<T, BaseClass>)),
(void)) function()
{
    //...
}


답변

기본 클래스에있는 템플릿 내부의 함수를 호출합니다.

이 함수에 액세스 할 수없는 유형으로 템플릿을 인스턴스화하려고하면 컴파일 타임 오류가 발생합니다.