2011-11-20 1 views
1

C++ 매개 변수화 된 클래스 집합을 작성 중이며 일부는 포인터와 유사하게 동작합니다. 특히, 상수가 아닌 템플릿 매개 변수가있는 개체의 상수 템플릿 매개 변수가있는 개체를 만들 수는 있지만 다른 방법은 사용할 수 없게하려고합니다. 나는 다음 클래스 계층 구조를 작성하여이 특정 행동을 달성 할 수 있었다올바른 포인터와 비슷한 동작 (상수에 대한 포인터)을 제공하기위한 대체 클래스 디자인?

int main() { 
    myClass<int> mc_int; 
    myClass<const int> mc_const_int; 

    myClass<const int> mc1(mc_const_int); // This should compile. 
    myClass<int> mc2(mc_int);    // This should compile. 
    myClass<const int> mc3(mc_int);  // This should compile. 
    myClass<int> mc4(mc_const_int);  // This should NOT compile. 
} 

(읽기 쉽도록 단순화) :이 샘플 코드는 내 의도를 명확히해야

template <typename T> 
class Base { 

    // ... 

protected: 

    template <typename U> 
    Base(const Base<U> &obj): _elem(obj._elem) {} 

private: 

    T _elem; 

    friend class Base<const T>; 
}; 

template <typename T> 
class myClass: public Base<T> { 

    // ... 

public: 

    template <typename U> 
    myClass(const myClass<U> &obj): Base<const U>(obj) {} 
}; 

을 그리고 그것은 작동 예상대로하지만, 나는 단지 생성자로부터 non-constant 템플릿 파라미터를 검출 할 수 있기 때문에이 설계에 완전히 만족하지는 않는다. 그러나 다른 어떤 멤버 함수로부터도 찾을 수는 없다.

내가 원하는 경우, 예를 들어, addAll() 방법 컨테이너 클래스를 만들려면,이 할 수 있도록하고 싶습니다 :

int main() { 
    Container<int> c_int; 

    c_int.add(new int(1)); 
    c_int.add(new int(2)); 
    c_int.add(new int(3)); 

    Container<const int> c_const_int; 

    c_const_int.addAll(c_int); // This should compile. 
    c_int.addAll(c_const_int); // This should NOT compile. 
} 

을하지만 이전 동작을 달성하는 방법을 모른다 . 누구든지 내가하려고하는 것을 달성하기 위해 대체 설계 아이디어가 있습니까? 누구든지이 문제가 더 깊이 논의되는 링크를 알고 있습니까?

미리 감사드립니다.

답변

1

이렇게하는 한 가지 방법은 부분 템플릿 전문화를 사용하는 것입니다.

template <typename T> 
struct MyClass { 
    void f(T&); 
}; 

그런 다음 전문화

template <typename T> 
struct MyClass<T const> { 
    void f(T&); 
    void f(T const&); 
}; 

불행하게도,이 중복을 코딩하는 리드

를 정의하지만, 당신이 무엇을 할 수 있도록해야합니다 : 당신이 일반적으로하는 것처럼 당신은 비 const 종류의 클래스를 정의해야합니다 필요. 당연히 함수를 MyClass<T>&MyClass<T const>&으로 사용할 수 있습니다.

+0

답장을 보내 주셔서 감사합니다. 제가 찾고있는 것이 정확하게 있습니다. 전체 클래스 대신 메서드를 특수화하여 해결 방법을 찾고 싶었지만 클래스에 대해 원하는 동작을 수행 할 수있는 방법이 없다고 생각합니다. 슬프게도, 내 수업은 500 줄에서 1000 줄로 진행되었지만, 그 행동이 원하는 것이면 괜찮습니다. – Kanopus

0

나는 약간의 질문을 이해하고 있습니다. 템플릿 전문화를 사용할 수 있습니다.

template <typename T> 
class container 
{ 
public: 
    template<typename U> 
    void addAll(const container<U>& b){} 
private: 
    template<> 
    void addAll(const container<int>&b); //No implementation 
}; 

container<int> b; 
.... 
container<const int> a; 
a.addAll(b) ; //Give a link error, I can't understand why vc2010 compile and run this line though 
0

하나의 가능성은 멤버 함수 템플릿을 사용하여 원하는 조합을 얻을 수 있도록하는 것입니다.

#include <utility> 

template <class T, class U> 
struct const_convertible; 

template <class T> 
struct const_convertible<T, T>: std::true_type {}; 

template <class T> 
struct const_convertible<T, const T>: std::true_type {}; 

template <class T> 
struct const_convertible<const T, T>: std::false_type {}; 

template <class T> 
class X 
{ 
public: 
    X() {} 
    X(const X&) {} //copy constructor 
    //conversion constructor as needed 
    template <class U> 
    X(const X<U>&, typename std::enable_if<const_convertible<U, T>::value, void>::type* = 0) 
    {} 

    template <class U> 
    typename std::enable_if<const_convertible<U, T>::value, void>::type f(X<U>) {} 
}; 

int main() 
{ 
    X<int> mut; 
    X<const int> con; 

    X<int> a(mut); 
    //X<int> b(con); 
    X<const int> c(mut); 
    X<const int> d(con); 

    mut.f(mut); 
    //mut.f(con); 
    con.f(mut); 
    con.f(con); 

    //X<double> doub; 
    //doub.f(mut); 
}