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

标签 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

最佳答案

建议:试试

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

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

而且你不能定义它 constexpr 因为它是使用 std::ref() 初始化的,它不是 constexpr

但是您对 ab 作为获取其类型大小的值不感兴趣;您只对 ab 类型感兴趣;所以你可以通过decltype(ab)

-- 编辑 --

离题建议。

您可以使用基于 std::index_sequence 的经典方式(以及模板折叠,从 C++17 开始可用),而不是 static_loop()

我的意思是...如果您定义一个 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(),如下所示

struct A {
    int a;
    int b;
    void run() {
        auto ab = std::make_tuple(std::ref(a), std::ref(b));
        int i { -1 };
        std::apply([&](auto & ... vs){ ((vs = ++i), ...); }, ab);
        std::cout << a << " " << b << std::endl;
    }
};

关于c++ - constexpr 模板参数的显式指定参数无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53978098/

相关文章:

c++ - std::tuple get() 成员函数

database - 数据库管理系统 : Meaning of the following Relational Calculus Example:

python - 如何在新行中打印列表中的元素?

c++ - 修改后的 std::invoke/std::apply,将可调用对象作为 void* - 可能吗?

c++ - 将函数引用传递到模板警告 : ignoring attributes on template argument 'func signature'

c++ - 具有 C++11 和线程支持的 Visual Express C++

c++ - 如何将二维数组作为只读传递给双指针函数?

c++ - 当我将 int 数据成员的初始化值更改为 1 以外的任何值时程序崩溃

c++ - Qt 以 60 FPS 刷新并吃掉 GPU

C++17 可变参数模板折叠