模板参数constexpr的显式指定参数无效

时间:2018-12-30 13:41:48

标签: c++ tuples c++17 template-meta-programming constexpr

我有一个static_loop构造

template <std::size_t n, typename F> void static_loop(F&& f) {
    static_assert(n <= 8 && "static loop size should <= 8");
    if constexpr (n >= 8)
        f(std::integral_constant<size_t, n - 8>());
    if constexpr (n >= 7)
        f(std::integral_constant<size_t, n - 7>());
    if constexpr (n >= 6)
        f(std::integral_constant<size_t, n - 6>());
    if constexpr (n >= 5)
        f(std::integral_constant<size_t, n - 5>());
    if constexpr (n >= 4)
        f(std::integral_constant<size_t, n - 4>());
    if constexpr (n >= 3)
        f(std::integral_constant<size_t, n - 3>());
    if constexpr (n >= 2)
        f(std::integral_constant<size_t, n - 2>());
    if constexpr (n >= 1)
        f(std::integral_constant<size_t, n - 1>());
}


template <typename T> constexpr size_t tupleSize(T) { return tuple_size_v<T>; }
struct A {
    int a;
    int b;
    void run() {
        auto ab = std::make_tuple(std::ref(a), std::ref(b));
        static_loop<tupleSize(ab)>([&](auto i) { std::get<i>(ab) = i; });
        std::cout << a << " " << b << std::endl;
    }
};

但是,它无法遍历上面列出的元组。

live godbolt example

2 个答案:

答案 0 :(得分:0)

建议:尝试

// .........VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
static_loop<std::tuple_size_v<decltype(ab)>>([&](auto i) { std::get<i>(ab) = i; });

我的意思是……您不能在常量表达式中使用ab(作为值),因为未定义ab constexpr

您无法定义它constexpr,因为它是使用不是std::ref()的{​​{1}}初始化的。

但是您对constexpr作为获取其类型大小的值不感兴趣;您仅对ab类型感兴趣;这样您就可以通过ab

-编辑-

非主题建议。

您可以使用基于decltype(ab)的经典方式(以及模板折叠,从C ++ 17开始可用)来代替static_loop()

我的意思是...如果您按以下方式定义std::index_sequence函数(使用run_1()助手)

run_1_helper()

您可以如下编写template <typename F, typename ... Ts, std::size_t ... Is> void run_1_helper (F const & f, std::tuple<Ts...> & t, std::index_sequence<Is...> const) { (f(std::get<Is>(t), Is), ...); } template <typename F, typename ... Ts> void run_1 (F const & f, std::tuple<Ts...> & t) { run_1_helper(f, t, std::index_sequence_for<Ts...>{}); }

A

或者,也许更好,只需使用struct A { int a; int b; void run() { auto ab = std::make_tuple(std::ref(a), std::ref(b)); run_1([](auto & v, auto i){ v = i; }, ab); std::cout << a << " " << b << std::endl; } }; ,如下所示

std::apply()

答案 1 :(得分:0)

更改

template <typename T>
constexpr size_t tupleSize(T) { return tuple_size_v<T>; }

收件人:

template <typename T>
constexpr size_t tupleSize(T const&) { return tuple_size_v<T>; }

也就是说,通过引用const而不是值来获取参数。照原样,您正在尝试以常量表达式复制非constexpr元组-这是行不通的。通过引用可以,因为您实际上并不在阅读元组。