2014-11-19 18 views
9

Tôi gặp một số rắc rối khi sử dụng các tham số mẫu của mẫu. Dưới đây là một ví dụ rất đơn giản:Sử dụng đúng các tham số mẫu mẫu C++

template <typename T> 
struct Foo { 
    T t; 
}; 

template <template <class X> class T> 
struct Bar { 
    T<X> data; 
    X x; 
}; 

int main() 
{ 
    Bar<Foo<int>> a; 
} 

Trình biên dịch (g ++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2) báo cáo các lỗi sau:

main.cpp:8:5: error: ‘X’ was not declared in this scope 
    T<X> data; 
    ^

main.cpp:8:6: error: template argument 1 is invalid 
    T<X> data; 
    ^

Bất kỳ ý tưởng gì là sai?

Trả lời

9

So I would like so make use of something like Bar<Foo<>>

template <typename T = int> 
struct Foo { 
    T t; 
}; 

template <typename T> 
struct Baz { 
    T t; 
}; 

template <typename T> 
struct Bar; 

template <template <typename> class T, typename X> 
struct Bar<T<X>> { 
    T<X> data; 
    X x; 
}; 

int main() 
{ 
    Bar<Foo<>> a; 
    Bar<Baz<float>> b; 
} 
+0

Ok, có vẻ tốt và biên dịch (Tôi vừa quên cờ -std = C++ 11). Nhưng tôi không hiểu giải pháp của bạn. Tại sao tuyên bố đầu tiên của 'Bar' được yêu cầu? –

+1

@ThomasWitkowski là * mẫu chính *, để tôi có thể chuyên dùng cho trường hợp 'struct Bar > '. nó không được hoàn thành một cách có chủ ý, để nó không được khởi tạo với kiểu khác với một mẫu tham số –

6
template <typename T> 
struct Foo { 
    T t; 
}; 

template <template <class> class T, class X> 
struct Bar { 
    T<X> data; 
    X x; 
}; 

int main() 
{ 
    Bar<Foo, int> a; 
} 
+1

Tại sao lưu ý lại? Chính xác. – Bathsheba

+2

@Bathsheba Có lẽ vì tôi không để lại lời giải thích nào. Nhưng thật kỳ lạ với tôi rằng tôi không thể nói nó thành những từ tiếng Anh. –

+1

Giải pháp này hơi không đạt yêu cầu. Vấn đề là, trong ví dụ thực, 'Foo' có một mặc định cho tham số mẫu, nói' int'.Vì vậy, tôi muốn sử dụng một cái gì đó như 'Bar >'. Bất kỳ cách nào để làm điều này? –

3

Trong

template <template <class X> class T> 

Biến X không phải là một mẫu tham số cho mẫu ngoài cùng: nó là một mẫu tham số để các mẫu trong cùng. Nó khá giống với

int foo(int (*bar)(int x)) 
{ 
    int y = x; // compiler error 
} 

mà không làm việc kể từ khi chức năng phải mất một đối số duy nhất, bar: không có tranh luận x.

Tùy thuộc vào những gì bạn thực sự cố gắng để làm, bạn có thể thêm các biến mẫu thứ hai, với một cái gì đó giống như

template <typename X, template <typename> class T > 
struct Bar 
{ 
    // ... 
}; 

bạn có thể giữ tờ khai với một biến duy nhất, nhưng đối sánh mẫu để cung cấp cho một đặc tả từng phần mà sẽ định nghĩa lớp trong ví dụ bối cảnh

template <typename T> 
struct Bar; 

template <typename X, template <typename> class T > 
struct Bar<T<X>> 
{ 
    // ... 
}; 

bạn có thể sửa đổi Foo để có một loại lồng hữu ích, và lấy nó như vậy

template <typename T> 
struct Bar 
{ 
    using X = T::value_type; 
}; 

hoặc bạn có thể định nghĩa một metafunction rằng chiết xuất một mẫu tham số từ một kiểu mẫu, và nhận được nó như vậy:

template <typename T> 
struct Bar 
{ 
    using X = get_parameter<T>; 
}; 

Các linh hoạt nhất là phiên bản cuối cùng, trừ trường hợp chứ không phải là một metafunction rằng chiết xuất mẫu đối số, bạn sẽ khai báo hàm get_bar_parameter và xác định chuyên môn từng phần trích xuất tham số mẫu từ Foo<X> (hoặc T<X>). Bằng cách đó, nếu bạn quyết định sử dụng Bar trong tương lai với các lớp có giá trị phù hợp của Xkhông phải là được tính theo cách đó, bạn có thể thực hiện việc này bằng cách cung cấp chuyên môn thích hợp cho get_bar_parameter.

0
// method 1 
template <typename T> 
struct Foo { 
    typedef T Type; 
    T t; 
}; 

template <typename T> 
struct Bar { 
    T data; 
    typename T::Type x; 
}; 

// method 2 
template <typename T> 
struct Hack 
{ 
    T t; 
}; 

template <typename T> 
struct TypeOf 
{ 
    typedef struct UnknownType Type; 
}; 

template<> 
struct TypeOf< Hack<int> > 
{ 
    typedef int Type; 
}; 

template <typename T> 
struct Baz { 
    T data; 
    typename TypeOf<T>::Type X; 
}; 

int main() 
{ 
    Bar< Foo<int> > a; 
    Baz< Hack<int> > b; 
    return 0; 
} 

Trong thông tin phương pháp 1 được cung cấp với loại lồng nhau. Điều này đòi hỏi phải thay đổi lớp gốc.

Trong phương pháp 2, thông tin này được cung cấp với chuyên môn của mẫu khác.

+1

Vui lòng thêm một số giải thích. –

+0

Thông thường bạn muốn cung cấp giải thích để đi kèm với mã của bạn khi đăng câu trả lời –

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