कंटेनर के रूप में टुपल्स तक पहुंचने के सुविधाजनक तरीकों के साथ प्रयोग करते समय, मैंने एक परीक्षण कार्यक्रम लिखा था।कौन सा कंपाइलर है, अगर किसी पैरामीटर पैक विस्तार में कोई बग है?
बजना (3.9.1, और सेब बजना) परयह संकलित की उम्मीद के रूप में, उम्मीद उत्पादन उत्पादन:
1.1
foo
2
जीसीसी पर
(5.4, 6.3), यह संकलन करने में विफल रहता है:
<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
प्रश्न: कौन सही है? क्या इसे ठीक किया जा सकता है?
कार्यक्रम:
#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;
}
}
मैं आपको इस प्रश्न में टैग 'भाषा-वकील' जोड़ने का सुझाव देता हूं, क्योंकि यह मानक –
@GuillaumeRacicot पर संकलक अनुरूपता के बारे में है। धन्यवाद। –
वैसे मुझे लगता है कि क्लैंग सही है क्योंकि कोड संकलित और अपेक्षा के अनुसार काम करता है और चूंकि जीसीसी संकलक त्रुटियों को फेंक रहा है, इसे वर्तमान संस्करण में लागू या तय नहीं किया जाना चाहिए था। – chbchb55