考虑以下代码:
#include <iostream>
#include <utility>
#include <array>
#include <functional>
#include <ctime>
template <unsigned N> void foo() { std::cout << N << "(" << ") "; }
template<> void foo<2>() { std::cout << "TWO (" << ") "; }
struct Foo {
template <unsigned N> void operator()(std::integral_constant<unsigned,N>) { foo<N>(); }
};
template <std::size_t Offset, std::size_t... Idx, typename F>
void visit(F f, std::index_sequence<Idx...>, std::size_t n) {
static std::array<std::function<void()>, sizeof...(Idx)> funcs {{
[&f](){f(std::integral_constant<unsigned,Idx+Offset>{});}...
}};
funcs[n - Offset]();
};
template <std::size_t Start, std::size_t End, typename F>
void visit(F f, std::size_t n) {
visit<Start>(f, std::make_index_sequence<End-Start>{}, n);
};
int main() {
auto t = time(nullptr);
for(int i = 0; i < 10; i++) {
visit<1, 10>(Foo{}, (t+i) % 10);
}
}
这是有效的C ++ 14(实际上,如果您编写自己的std::index_sequence
也是有效的C ++ 11)。但是-它无法使用g ++ 6.x和7.x进行编译;只有g ++ 8.x可以正确编译它(请参阅发生的on GodBolt)。
出于组织原因,我可以要求使用7.2之前的g ++版本。有什么办法可以在保留语义的同时更改代码,以使g ++ 7.x对其进行编译?
答案 0 :(得分:2)
GCC的错误是它不能打包扩展lambda。因此,请勿打包扩展lambda。
template<class F, std::size_t Idx>
void caller(F& f) { f(std:::integral_constant<unsigned, Idx>()); }
template <std::size_t Offset, std::size_t... Idx, typename F>
void visit(F f, std::index_sequence<Idx...>, std::size_t n) {
using ptr_type = void (*)(F&);
static constexpr ptr_type funcs[] = {&caller<F, Idx+Offset>...};
funcs[n-Offset](f);
}
答案 1 :(得分:0)
我用一块石头和expanded this visitation mechanism to functions taking an arbitrary number of arguments打了两只鸟。 whaddaya知道-这意味着将lambda移入辅助函数,以避免不同的参数包相互干扰。作为@ T.C。建议-这就是GCC遇到的麻烦,因此可以避免此问题。
template <std::size_t N, typename F, typename... Ts>
std::function<void(Ts...)> make_visitor(F f) {
return
[&f](Ts... args) {
f(std::integral_constant<std::size_t,N>{}, std::forward<Ts>(args)...);
};
}
template <std::size_t Offset, std::size_t... Idx, typename F, typename... Ts>
void visit(F f, std::index_sequence<Idx...>, std::size_t n, Ts... args) {
static std::array<std::function<void(Ts...)>, sizeof...(Idx)> funcs {{
make_visitor<Idx+Offset, F, Ts...>(f)...
}};
funcs[n-Offset](std::forward<Ts>(args)...);
};
template <std::size_t Start, std::size_t End, typename F, typename... Ts>
void visit(F f, std::size_t n, Ts... args) {
visit<Start>(f, std::make_index_sequence<End-Start>{}, n, std::forward<Ts>(args)...);
};