Khi thử nghiệm với các cách thuận tiện để truy cập bộ dữ liệu dưới dạng vùng chứa, tôi đã viết một chương trình thử nghiệm.Trình biên dịch nào, nếu có lỗi trong việc mở rộng gói tham số?
trên kêu vang (3.9.1, và kêu vang táo) nó biên dịch như mong đợi, sản xuất sản lượng dự kiến:
1.1
foo
2
trên gcc (5.4, 6.3), nó thất bại trong việc biên dịch:
<source>: In lambda function:
<source>:14:61: error: parameter packs not expanded with '...':
+[](F& f, Tuple& tuple) { f(std::get<Is>(tuple)); }...
^
<source>:14:61: note: 'Is'
<source>: In function 'decltype(auto) notstd::make_callers_impl(std::index_sequence<Is ...>)':
<source>:14:64: error: expansion pattern '+<lambda>' contains no argument packs
+[](F& f, Tuple& tuple) { f(std::get<Is>(tuple)); }...
^~~
Compiler exited with result code 1
Câu hỏi: ai đúng? Nó có thể được sửa?
Chương trình:
#include <iostream>
#include <array>
#include <tuple>
namespace notstd {
template<class F, class Tuple, std::size_t...Is>
auto make_callers_impl(std::index_sequence<Is...>) -> decltype(auto)
{
static std::array<void (*) (F&, Tuple&), sizeof...(Is)> x =
{
+[](F& f, Tuple& tuple) { f(std::get<Is>(tuple)); }...
};
return x;
};
template<class F, class Tuple>
auto make_callers() -> decltype(auto)
{
return make_callers_impl<F, Tuple>(std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
};
template<class Tuple, std::size_t N = std::tuple_size<std::decay_t<Tuple>>::value >
struct tuple_iterator {
static constexpr auto size = N;
constexpr tuple_iterator(Tuple& tuple, std::size_t i = 0) : tuple(tuple), i(i) {}
template<class F>
void with(F&& f) const {
static const auto& callers = make_callers<F, Tuple>();
callers[i](f, tuple);
}
constexpr bool operator!=(tuple_iterator const& r) const {
return i != r.i;
}
constexpr auto operator++() -> tuple_iterator& {
++i;
return *this;
}
Tuple& tuple;
std::size_t i;
};
template<class Tuple>
auto begin(Tuple&& tuple)
{
return tuple_iterator<Tuple>(std::forward<Tuple>(tuple));
}
template<class Tuple>
auto end(Tuple&& tuple)
{
using tuple_type = std::decay_t<Tuple>;
static constexpr auto size = std::tuple_size<tuple_type>::value;
return tuple_iterator<Tuple>(std::forward<Tuple>(tuple), size);
}
}
template<class T> void emit(const T&);
int main() {
auto a = std::make_tuple(1.1, "foo", 2);
auto i = notstd::begin(a);
while(i != notstd::end(a))
{
i.with([](auto&& val) { std::cout << val << std::endl; });
++i;
}
}
Tôi đề nghị bạn thêm thẻ 'language-lawyer' vào câu hỏi này, vì nó phù hợp về trình biên dịch với tiêu chuẩn –
@GuillaumeRacicot được thực hiện. cảm ơn bạn. –
Vâng tôi đoán rằng Clang là đúng vì mã biên dịch và hoạt động như mong đợi và vì gcc đang ném lỗi trình biên dịch, nó không phải đã được triển khai hoặc sửa trong phiên bản hiện tại. – chbchb55