Có, nhưng không trực tiếp:
template <typename Item, template <typename> class Container>
struct TList
{
typedef typename Container<Item>::type type;
};
Sau đó, bạn có thể xác định chính sách container khác nhau:
template <typename T>
struct vector_container
{
typedef std::vector<T> type;
};
template <typename T>
struct map_container
{
typedef std::map<T, std::string> type;
};
TList<int, vector_container> v;
TList<int, map_container> m;
Mặc dù có một chút chi tiết. * Để thực hiện mọi việc trực tiếp, bạn cần phải thực hiện the route described by James, nhưng khi ghi chú điều này là cuối cùng rất không linh hoạt.
Tuy nhiên, với C++ 0x chúng ta có thể làm điều này chỉ tốt:
#include <map>
#include <vector>
template <typename Item,
template <typename...> class Container, typename... Args>
struct TList
{
// Args lets the user specify additional explicit template arguments
Container<Item, Args...> storage;
};
int main()
{
TList<int, std::vector> v;
TList<int, std::map, float> m;
}
Perfect. Thật không may là không có cách nào để tái tạo điều này trong C++ 03, ngoại trừ thông qua các lớp chính sách gián tiếp giới thiệu như mô tả ở trên.
* Tôi muốn nhấn mạnh rằng "Chi tiết một chút" có nghĩa là "điều này không chính thống". Giải pháp chính xác cho vấn đề của bạn là thư viện chuẩn, as Jerry explains. Bạn chỉ cho phép người dùng adapter container của bạn chỉ định toàn bộ container loại trực tiếp:
template <typename Item, typename Container = std::vector<Item>>
struct TList
{};
Nhưng vẫn để lại một vấn đề lớn: những gì nếu tôi không muốn kiểu giá trị của các container để được Item
nhưng something_else<Item>
? Nói cách khác, làm cách nào tôi có thể thay đổi loại giá trị của vùng chứa hiện tại thành vùng chứa khác? Trong trường hợp của bạn, bạn không nên đọc thêm, nhưng trong trường hợp chúng tôi làm, chúng tôi muốn rebind một vùng chứa.
Thật không may cho chúng tôi, các container không có chức năng này, mặc dù allocators làm:
template <typename T>
struct allocator
{
template <typename U>
struct rebind
{
typedef allocator<U> type;
};
// ...
};
Điều này cho phép chúng tôi để có được một allocator<U>
đưa ra một allocator<T>
. Làm thế nào chúng ta có thể làm tương tự cho các thùng chứa mà không có tiện ích xâm nhập này? Trong C++ 0x, thật dễ dàng:
template <typename T, typename Container>
struct rebind; // not defined
template <typename T, typename Container, typename... Args>
struct rebind<T, Container<Args...>>
{
// assumes the rest are filled with defaults**
typedef Container<T> type;
};
Với std::vector<int>
, chúng tôi có thể thực hiện rebind<float, std::vector<int>>::type
, ví dụ. Không giống như C++ 0x trước giải pháp, chương trình này có thể được mô phỏng trong C++ 03 với các macro và lặp ..
** Chú ý cơ chế này có thể được thực hiện mạnh mẽ hơn nhiều, giống như đó nêu rõ lý lẽ để giữ , mà để rebind, mà để rebind mình trước khi sử dụng như là đối số, vv, nhưng đó là trái như là một tập thể dục cho người đọc. :)
Ai sẽ sử dụng lớp này? Tại sao 'List' không thể sử dụng' typedef vector/list/set- items'? Điều gì sẽ là mục đích của một lớp học, được đưa ra một loại container và một loại giá trị, chỉ cần đặt cả hai với nhau? –
UncleBens
Re: chỉnh sửa, vẫn không thấy lý do tại sao bạn không thể viết danh sách 'List>;' etc –
UncleBens