Sau khi đọc một bài viết tuyệt vời True Story: Efficient Packing tôi cố gắng thực hiện tuple bởi bản thân mình như tập thể dục:Gọi đến chức năng là mơ hồ khi loại không thích hợp định nghĩa là bí danh
#include <type_traits>
#include <utility>
#include <functional>
template< std::size_t I, typename T >
struct tuple_leaf { T value; };
template< std::size_t I, typename T >
T & get(tuple_leaf< I, T > & leaf)
{ return leaf.value; }
template< typename Is, typename ...Ts >
struct tuple_base;
template< std::size_t ...Is, typename ...Ts >
struct tuple_base< std::index_sequence<Is...>, Ts... >
: tuple_leaf< Is, Ts >...
{
using tuple_base_t = tuple_base;
template< typename ...Args, typename = std::enable_if_t< (sizeof...(Ts) == sizeof...(Args)) > >
tuple_base(Args &&... args)
: tuple_leaf< Is, Ts >{std::forward<Args>(args)}...
{ ; }
};
#if 0
template< typename ...Ts >
struct tuple
: tuple_base< std::index_sequence_for<Ts...>, Ts... >
{
using tuple_base_t = typename tuple::tuple_base_t;
using tuple_base_t::tuple_base_t;
using tuple_base_t::operator = ;
};
#else
// terse
template< typename ...Ts >
using tuple = tuple_base< std::index_sequence_for<Ts...>, Ts... >;
#endif
template< typename ...Args >
tuple< Args &&... >
forward_as_tuple(Args &&... args)
{ return {std::forward<Args>(args)...}; }
#include <tuple>
int
main()
{
tuple<int> t(1);
auto f = forward_as_tuple(t);
(void)f;
return 0;
}
Sau khi thực hiện forward_as_tuple
tôi quyết định thay đổi định nghĩa của tuple
loại từ mẫu lớp đến mẫu bí danh của mẫu lớp cơ sở của nó, bởi vì tất cả những gì tôi cần tách thành lớp tuple
chính nó và lớp triển khai thực hiện tuple_base
chỉ là std::index_sequence_for
đối với gói thông số loại mẫu có biến thể - mẫu bí danh là công cụ phù hợp chính xác cho mục đích này. Sau khi thực hiện mà tôi nhận được một lỗi (#if 0
trường hợp):
error: call to 'forward_as_tuple' is ambiguous
Có vẻ lạ đối với tôi, vì alias mẫu làm gì cả và mặt khác forward_as_tuple
gọi cho loại hình từ không gian tên tương tự - Tôi đã hy vọng rằng ADL nên làm việc cho trường hợp trên chắc chắn.
Cách giải thích sự khác biệt giữa các phiên bản mã #if 1
và #if 0
?
'std :: index_sequence_for' trở thành một đối số mẫu kiểu của loại đối số của một cuộc gọi hàm, do đó,' std' được kiểm tra bởi ADL. BTW. Bạn sẽ gặp lỗi tương tự nếu bạn sử dụng 'tuple' trực tiếp –
@PiotrSkotnicki Khoảnh khắc tinh tế. Tôi luôn ghi nhớ rằng ADL chỉ dành cho các kiểu đối số hàm, nhưng cũng cho các tham số mẫu. – Orient
@PiotrSkotnicki 'tuple_base, int>>, tuple_base , int>>' là đối số hàm. 'std :: index_sequence_for' nằm sâu bên trong. I E. nó không phải là tên mẫu hàng đầu. Nó có quan trọng không? –
Orient