developer tip

템플릿 제약 C ++

copycodes 2020. 12. 3. 08:01
반응형

템플릿 제약 C ++


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제안을 추천합니다 .

편집 : Boost 에는 자체 .

Edit2 : C ++ 0x에서 개념이 제거 된 것 같습니다 .


C ++ 11을 사용 static_assert하는 std::is_base_of경우이 목적으로 with 사용할 수 있습니다 .

예를 들면

#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);

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

This works because C++ compiles a new version of the templatized function (or class) for each instantiation. As it performs that compilation, it makes a direct, almost macro-like substitution of the template instantiation into the code prior to type-checking. If everything still works with that template, then compilation proceeds and we eventually arrive at a result. If anything fails (like int* not declaring length()), then we get the dreaded six page template compile-time error.


You can put a guard type on IFoo that does nothing, make sure it's there on T in Foo:

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

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

Check out Boost

The Boost Concept Check Library (BCCL)

The Concept Check library allows one to add explicit statement and checking of concepts in the style of the proposed C++ language extension.


Sort of. If you static_cast to an IFoo*, then it will be impossible to instantiate the template unless the caller passes a class that can be assigned to an IFoo *.


Only implicitly.
Any method you use in a method that is actually called is imposed on the template parameter.


You can do it. Create the base template. Make it have only Private constructors. Then create specializations for each case you want to allow (or make the opposite if the disallowed list is much smaller than the allowed list).

The compiler will not allow you to instantiate the templates that use the version with private constructors.

This example only allow instantiation with int and float.

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

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

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

Its not a short and elegant way of doing it, but its possible.


Look at the CRTP pattern (Curiously Recursive Template Pattern). It is designed to help support static inheritence.

참고URL : https://stackoverflow.com/questions/122316/template-constraints-c

반응형