2010-02-21 38 views
5

Câu hỏi này có liên quan đến số one cuối cùng của tôi. Tôi đang cố giải quyết vấn đề bằng cách sử dụng traits<T>traits<T*>. Vui lòng xem xét mã sau đây.Sử dụng các đặc điểm trong C++

template<typename T> 
struct traits 
{ 
    typedef const T& const_reference; 
}; 

template<typename T> 
struct traits<T*> 
{ 
    typedef const T const_reference; 
}; 

template<typename T> 
class test 
{ 
public: 
    typedef typename traits<T>::const_reference const_reference; 
    test() {} 
    const_reference value() const { 
     return f; 
    } 
private: 
    T f; 
}; 

int main() 
{ 
    const test<foo*> t; 
    const foo* f = t.value(); // error here. cannot convert ‘const foo’ to ‘const foo*’ in initialization 
    return 0; 
} 

Vì vậy, nó trông giống như trình biên dịch không được xem xét đặc điểm chuyên môn cho con trỏ và tham kiểu trả về của value() như const foo hơn const foo*. Tôi làm gì sai ở đây?

Mọi trợ giúp sẽ tuyệt vời!

Trả lời

2

Chuyên môn đang được sử dụng. traits<foo*>::const_referenceconst foo. Nếu bạn muốn nó được một con trỏ, sử dụng:

template<typename T> 
struct traits<T*> 
{ 
    typedef const T* const_reference; 
}; 

Với điều này, traits<foo*>::const_reference sẽ const foo*.

Lưu ý rằng việc sử dụng T trong chuyên môn traits<T*> hoàn toàn tách biệt với T trong mẫu traits. Bạn có thể đổi tên:

template<typename U> 
struct traits<U*> 
{ 
    typedef const U* const_reference; 
}; 

và bạn sẽ có cùng một chuyên môn. Nó có ý nghĩa hơn nếu bạn đã trải nghiệm trong lập trình hàm.

Để bắt đầu, hãy nghĩ đến số template <typename ...> khi giới thiệu một trừu tượng, thay vì một hàm tóm tắt một giá trị. Nó giống như quay

sum = 0 
for item in [1,2,3]: 
    sum += item 

thành:

function sum(l): 
    sum = 0 
    for item in l: 
     sum += item 
    return sum 

nơi l mất nơi [1,2,3]. Chúng ta có thể gọi sums từ một chức năng mà bản thân có một tham số chính thức được đặt tên l:

function sumsq(l): 
    return sum(map(lambda x: x*x, l)) 

sumsq 's 'l' không có gì để làm với sum' s 'l'.

Với mẫu, chúng tôi trừu tượng tên loại thay vì giá trị. Nghĩa là, chúng ta lần lượt:

struct traits { 
    typedef const double& const_reference; 
}; 

thành:

template <typename T> 
struct traits { 
    typedef const T& const_reference; 
}; 

Bây giờ xem xét một tổ chức phi mẫu chuyên môn:

template <> 
struct traits<double*> { 
    typedef const double* const_reference; 
}; 

Ở đây không có thông số mẫu cho chuyên môn hóa, nhưng bạn có thể hãy suy nghĩ của traits<double*> khi áp dụng mẫu traits cho một double*. Tóm tắt ra double và bạn có:

template <typename T> 
struct traits<T*> { 
    typedef const T* const_reference; 
}; 

Ở đây T là một tham số cho chuyên môn, không phải là mẫu cơ sở.

+0

Tôi cảm thấy đổ: (Nhưng, T chính nó là một con trỏ ('foo *'). Vì vậy, chỉ định 'T *' sẽ dẫn vào 'T **'? –

+0

Không. Trong đặc điểm 'đặc điểm ', 'T 'không phải là một con trỏ,' T * 'là một con trỏ.Đó là bạn sử dụng cùng một tham số kiểu tên là không quan trọng .. – outis

+0

OK. –

Các vấn đề liên quan