2012-09-19 43 views
6

Tôi đang sử dụng chức năng mẫu để xây dựng đối tượng để tạo đối tượng từ dữ liệu phản chiếu và hoạt động khá tốt, nhưng bây giờ tôi muốn hỗ trợ loại vùng chứa STL trong hệ thống phản chiếu sao cho các đối tượng như:C++ Nhận loại Vector

// Note - test case only 
// for real world usage it would probably not be structured like this 
// and the phrases would be mapped by an id or something 
struct Phrases { 
    std::vector<std::string> phrases; 
}; 

typedef std::string Lang; 
struct Langs { 
    std::map< Lang, Phrases > translations; 
}; 

Có thể được hỗ trợ. Tôi có thể thực hiện một số phép thuật regex trên sự trở lại của

typeid(object).name() 

để tìm hiểu xem đối tượng là một vectơ hoặc bản đồ và đối số tham số cho đối tượng là gì. Và tôi đã thử một số mẫu ma thuật để làm điều gì đó như sau, trong đó CreateString, ConstructString & DestroyString đang đứng trong các hàm và dữ liệu cũng phù hợp với điều gì đó phức tạp hơn một chút sử dụng cơ sở dữ liệu kiểu để xử lý đối tượng.

// Representational of code, basically a copy-paste to a different test project where I can work out the problems with this specific vector problem 
// Vector specialised construction 
template <typename T> void ConstructVector(void* object, const std::vector<std::string>& data) { 
    T* vec = (T*)object; 
    Name vector_type = GetVectorTypeName<T>(); 

    void *obj; 
    CreateString(&obj); 
    // All fields in this type should be valid objects for this vector 
    for(std::vector<std::string>::const_iterator it = data.begin(), end = data.end(); it != end; ++it) { 
    // Push it 
    vec->push_back(*obj); 
    // Get address to new instance 
    void *newly = &vec->back(); 
    ConstructString(newly,*it); 
    } 
    DestroyString(&obj); 

} 

Điều này không hoạt động do việc bỏ qua bất hợp pháp với "vec-> push_back (* obj);" mà tôi không thể làm được vì tôi không biết loại đó. Về cơ bản những gì tôi cần để có thể làm là tạo ra vectơ này với một số phần tử chưa được đặt sẵn trong nó, hoặc thêm các phần tử mới vào nó mà không thực sự có kiểu, bởi vì nếu tôi có thể lấy một con trỏ tới khối bộ nhớ bên trong vectơ, tôi có thể cuộn với điều đó và xây dựng đối tượng. Nhưng vector thêm các yêu cầu như

vector::push_back(T& value) 

hoặc

vector::insert(Iter&, T&) 

sẽ không làm việc cho tôi, trừ khi tôi có thể có được bàn tay của tôi trên kiểu T từ bên trong mẫu

pastebin mã kiểm tra để thử và giải quyết vấn đề này: http://pastebin.com/1ZAw1VXg

Vì vậy, câu hỏi của tôi là, làm cách nào tôi có thể nhận phần std :: string của std :: khai báo vector khi tôi ở trong một mẫu như

template <typename T> void SomeFunc() { 

    // Need to get std::string here somehow  
    // Alternatively need to make the vector a certain size and then 
    // get pointers to it's members so I can construct them 
} 


SomeFunc<std::vector<std::string>>>(); 
+1

Lệnh 'std :: vector' có một 'typedef T value_type' bên trong nếu đó là những gì bạn cần. –

Trả lời

15

Có hai cách để thực hiện việc này.

1) Hoặc bạn tận dụng thực tế là std::vector<> (giống như tất cả các lớp chứa thư viện tiêu chuẩn) duy trì một loại thành viên value_type, đại diện cho các loại của các nguyên tố lưu trữ trong các vector. Vì vậy, bạn có thể làm điều này:

template <typename T> void SomeFunc() { 
    typename T::value_type s; // <--- declares a `std::string` object 
          //  if `T` is a `std::vector<std::string>` 
} 

2) Hoặc nếu không, bạn thay đổi tuyên bố chức năng của bạn và sử dụng mẫu template thông số:

template <template <typename> class T, typename Elem> 
void SomeFunc(T<Elem> &arg) 
{ 
    Elem s; 
} 

Tuy nhiên, có một vấn đề nhỏ với rằng: std::vector thực sự là một mẫu có hai tham số (kiểu phần tử và kiểu phân bổ), điều này làm cho việc sử dụng các tham số mẫu của mẫu trở nên khó khăn và vẫn giữ cú pháp đơn giản.Một điều mà làm việc đối với tôi là để tuyên bố một bí danh của các loại vector mà lá chỉ có một mẫu số:

template <typename Elem> 
using myvector = std::vector<Elem>; 

Sau đó, tôi có thể sử dụng SomeFunc như thế này:

int main() 
{ 
    myvec<std::string> vec; 
    SomeFunc(vec); 
} 
+0

Cảm ơn vì điều đó, nó sẽ cho phép tôi tạo ra một phiên bản chức năng sạch hơn nhiều so với giải pháp mà tôi đã tấn công. – kyall