コンテナとしてタプルにアクセスするための便利な方法を試してたとき、私はテストプログラムを書きました。パラメータ・パックの拡張にバグがあるコンパイラはどれですか?
打ち鳴らす(3.9.1、及びリンゴ打ち鳴らす)に予想通り、それは期待される出力生成、コンパイル:GCCで
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にコンパイラの適合性についてですので、あなたは、この質問にタグ '言語lawyer'を追加することをお勧めします。ありがとうございました。 –
さて私は、コードをコンパイルし、期待どおりに動作し、gccがコンパイルエラーを投げているので、それが実現したり、現在のバージョンで修正されていてはなりませんので、クランが右であることを推測すると思います。 – chbchb55