Điều này thực sự có thể thực hiện được, với các tính năng C++ 11.
Có initializer_list muốn tất cả phần tử của nó phải cùng loại. Bí quyết là chúng ta có thể tạo ra một lớp wrapper mà có thể static_cast
cho tất cả các loại chúng ta muốn. Đây là dễ dàng để đạt được:
template <typename... tlist>
class MultiTypeWrapper {
};
template <typename H>
class MultiTypeWrapper<H> {
public:
MultiTypeWrapper() {}
MultiTypeWrapper(const H &value) : value_(value) {}
operator H() const {
return value_;
}
private:
H value_;
};
template <typename H, typename... T>
class MultiTypeWrapper<H, T...>
: public MultiTypeWrapper<T...> {
public:
MultiTypeWrapper() {}
MultiTypeWrapper(const H &value) : value_(value) {}
// If the current constructor does not match the type, pass to its ancestor.
template <typename C>
MultiTypeWrapper(const C &value) : MultiTypeWrapper<T...>(value) {}
operator H() const {
return value_;
}
private:
H value_;
};
Với các nhà thầu chuyển đổi ngầm, chúng ta có thể vượt qua một cái gì đó như {1,2.5, 'c', 4} để một initializer_list (hoặc vector, mà mặc nhiên chuyển đổi initializer_list) loại MultiTypeWrapper. Điều này có nghĩa rằng chúng ta không thể viết một hàm như dưới chấp nhận intializer_list như lập luận:
template <typename... T>
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) {
....
}
Chúng tôi sử dụng thủ thuật khác để cast mỗi giá trị trong các vector để loại ban đầu của nó (lưu ý rằng chúng tôi cung cấp chuyển đổi ngầm trong định nghĩa của MultiTypeWrapper
) và gán nó vào vị trí tương ứng trong một bộ tuple. Nó giống như một đệ quy trên lập luận mẫu:
template <int ind, typename... T>
class helper {
public:
static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) {
std::get<ind>(t) = static_cast<typename std::tuple_element<ind,std::tuple<T...> >::type>(v[ind]);
helper<(ind-1),T...>::set_tuple(t,v);
}
};
template <typename... T>
class helper<0, T...> {
public:
static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) {
std::get<0>(t) = static_cast<typename std::tuple_element<0,std::tuple<T...> >::type>(v[0]);
}
};
template <typename... T>
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) {
std::tuple<T...> res;
helper<sizeof...(T)-1, T...>::set_tuple(res, init);
return res;
}
Lưu ý rằng chúng ta phải tạo ra các lớp helper cho set_tuple
từ C++ không hỗ trợ chức năng chuyên môn.Bây giờ nếu chúng ta muốn kiểm tra mã:
auto t = create_tuple<int,double,std::string>({1,2.5,std::string("ABC")});
printf("%d %.2lf %s\n", std::get<0>(t), std::get<1>(t), std::get<2>(t).c_str());
Kết quả sẽ là:
1 2.50 ABC
này được thử nghiệm trên máy tính để bàn của tôi với kêu vang 3.2
Hy vọng đầu vào của tôi giúp :)
Lấy làm tiếc! Tôi đã thực hiện một lỗi đánh máy, chỉnh sửa lại, nhưng vẫn không hoạt động! – Need4Steed
@ Need4Steed Đã cập nhật câu trả lời của tôi. –
Tôi đã thử make_tuple, nó hoạt động tốt, nhưng nó có vẻ không phù hợp với tôi nếu nó ổn với cặp nhưng không đi với tuple. – Need4Steed