2011-07-03 39 views

Trả lời

0
  1. Điều này có thể tạo ánh xạ biên dịch từ loại -> thành viên tĩnh của A.

    template<typename> 
    struct sort_statistics { static size_t times_comparator_called = 0; }; 
    
    template<typename T> 
    size_t sort_statistics<T>::times_comparator_called; 
    
    template<typename Titer> 
    void my_sort(Titer first, Titer last) 
    { 
        //... 
        ++sort_statistics<iterator_traits<Titer>::value_type>::times_comparator_called; 
        if (*itA < *itB) { 
        //... 
    } 
    
  2. Nó vẫn có thể được chuyên môn hóa.

+1

Bạn có thể giải thích chi tiết về điểm 1 không? – iammilind

+0

@iammiling: Làm thế nào? –

3

Bạn có thực sự thấy rằng việc sử dụng cho định nghĩa mẫu không, ví dụ, không phải là khai báo mẫu?

Một số sử dụng:

// declaration only: the parameter name has no use beyond documentation 
template<typename> 
struct A; 

// this is fine 
template<typename T> 
void eat_an_a(A<T> a); 

// later, we can name the parameter to use it 
template<typename T> 
struct A { ... }; 

// C++0x only 
template< 
    typename T 
    // We don't care for the actual type (which will default to void) 
    // the goal is sfinae 
    , typename = typename std::enable_if< 
     std::is_array<typename std::decay<T>::type>::value 
    >::value 
> 
void 
f(T&& t); 

// We still don't care to name that defaulted parameter 
template<typename T, typename> 
void f(T&& t) 
{ ... } 

Lời giải thích cho trường hợp rất đặc biệt mà bạn có liên quan đến đã được đưa ra bởi Johannes, nhưng dường như bạn đã tìm thấy nó không đạt yêu cầu. Tôi sẽ hướng dẫn bạn cách làm việc này. Hãy cho chúng tôi giả định một đặc điểm tùy ý:

// no definition 
template<typename TypeToExamine, typename ImplementationDetail = void> 
struct trait; 

Tôi viết đúng vai trò của các thông số loại trong tên của chúng. Bây giờ những gì khai báo này cho phép, vì tham số thứ hai được mặc định, là một chút đường cú pháp. Bất cứ nơi nào trait<U> xuất hiện, chính là chính xác như thể chúng tôi đã viết trait<U, void> đã được viết. Bây giờ chúng ta hãy cung cấp định nghĩa cho trường hợp cơ sở của đặc điểm của chúng tôi:

// assume previous declaration is still in scope so we do not default 
// the second parameter again 
template<typename T, typename> struct trait: std::false_type {}; 

Nó không phải là một đặc điểm rất hữu ích. Bây giờ, khi chúng tôi viết trait<U>, viết tắt là trait<U, void>, chúng tôi sẽ kết thúc với định nghĩa này. Điều này có nghĩa là trait<U>::value hợp lệ và thực tế là false. Hãy làm cho lớp của chúng tôi hữu ích hơn bằng cách thêm các thành phần bí mật:

template<typename> struct void_ { typedef void type; }; 
// again, assume previous declarations are in scope 
template<typename T, typename void_<decltype(T() + T())>::type> 
struct trait: std::true_type {}; 

Một lần nữa, khi chúng ta viết trait<U>, nó như thể chúng tôi đã viết trait<U, void>. Chuyên môn từng phần không thay đổi điều đó (nó không được phép). Nhưng chúng ta nên sử dụng định nghĩa nào khi truy vấn trait<U>::value? Đầu tiên, chúng ta phải biết chính xác chuyên môn nào phù hợp; hoặc, đối số thứ hai bí ẩn typename void_<decltype(T() + T())>::type là gì?

Trường hợp đơn giản nhất là khi U() + U() không đúng định dạng. Sau đó, SFINAE đá vào và dường như chuyên môn không tồn tại; do đó, chúng tôi có được định nghĩa không chuyên biệt và valuefalse. Tuy nhiên, nếu U() + U() được tạo đúng, thì decltype sẽ tạo ra một loại và toàn bộ biến thành void, vì tất cả các loại void_<T>::typevoid. Vì vậy, điều này có nghĩa rằng chúng tôi có một chuyên môn của mẫu trait<T, void>. Điều này có thể khớp với trait<U>, chỉ cần đối sánh T với U. Và bây giờ valuetrue.

Tuy nhiên, nếu chuyên môn đã được viết

template<typename T> 
struct trait<T, decltype(T() + T())>: std::true_type {}; 

thì cách duy nhất nó sẽ được sử dụng là khi viết trait<U, decltype(U() + U())>, trừdecltype(U() + U()) happended để được bãi bỏ. Hãy nhớ rằng, trait<U> là đường cho trait<U, void>. Vì vậy, trait<int> sẽ không bao giờ khớp với chuyên môn của chúng tôi bởi vì sau này có dạng trait<int, int>.

Vì vậy, void_ đóng vai trò luôn có chuyên môn của biểu mẫu trait<T, void> nếu chúng không phải là SFINA. Vì chúng ta không quan tâm đến việc sử dụng tham số kiểu, nó không được đặt tên.

+0

Không, tôi chưa thấy trong bản khai báo trước. Nó được sử dụng để xác định một cơ thể 'lớp' là tốt. Xem tại đây: http://stackoverflow.com/questions/6540948/c-templates-how-to-determine-if-a-type-is-suitable-for-subclassing?answertab=votes#tab-top – iammilind

+0

@iammilind Nên đã đặt liên kết đó vào câu hỏi! Sau đó chúng tôi có thể đã hoàn toàn chỉ ra bạn ** không bao giờ ** thấy 'mẫu struct A ...'. Bạn đã thấy 'template struct A ...'. Đó là * rất nhiều * khác nhau, được mô tả một phần trong các bình luận bên trong liên kết của bạn, và bạn có thể thấy cách sử dụng khác của một tham số mặc định ẩn danh trong câu trả lời của tôi. –

+0

nó không liên quan 'typename = void'. xem trong câu trả lời: 'mẫu struct void_ {typedef void type; }; ' – iammilind

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