循环模板与非常量参数

huangapple go评论60阅读模式
英文:

template for loop with non-const arguments

问题

cpp中,你可以使用两个秘籍来有效地在模板参数上实现一个for循环,编译器将接受这样做。如下所示。

template<size_t k> void increment(size_t* v, size_t& i){ v[k]=i*i++; }

int main(){
    const size_t N = 10;
    size_t v[N], i=0;

    // for(size_t k=0;k<N;++k){ increment<k>(v,i); } // 这样不会工作
    
    // 所以我们写下以下内容
    [v,i]<std::size_t... Is>(std::index_sequence<k...>){ // 这行是第一个秘籍
        (increment<k>(v,i), ...); // 循环体
    }(std::make_index_sequence<N>{}); // 这行是第二个秘籍
    
    for(size_t k=0;k<N;++k){ std::cout << v[k] << " , "; }
}
英文:

In cpp you can use two cheat codes to effectively have a for-loop over template arguments, which the compiler will accept. This is shown below.

#include &lt;iostream&gt;
#include &lt;memory&gt;

template&lt;size_t k&gt; void increment(size_t* v, size_t&amp; i){ v[k]=i*i++; }

int main(){
    const size_t N = 10;
    size_t v[N], i=0;

    // for(size_t k=0;k&lt;N;++k){ increment&lt;k&gt;(v,i); } // this would not work
    
    // so we write the following instead
    [v,i]&lt;std::size_t... Is&gt;(std::index_sequence&lt;k...&gt;){ // this line is the first cheat code
        (increment&lt;k&gt;(v,i), ...); // loop body
    }(std::make_index_sequence&lt;N&gt;{}); // this line is the second cheat code
    
    for(size_t k=0;k&lt;N;++k){ std::cout &lt;&lt; v[k] &lt;&lt; &quot; , &quot;; }
}

Question: The code won't compile because in the line loop body, the compiler requires v,i to be const. But as the example points out, I do not want them const. Thus, I am asking for that cheat code, which makes it work. If multiple cheat codes exist, I want the shortest.

答案1

得分: 6

The mutable keyword can be used to allow a lambda expression to modify objects it captures by value.

You also need to capture v by reference or increment will be called on a copy of v and have no visible effect.

Live example: https://godbolt.org/z/4xbPe4MdP

#include <iostream>
#include <memory>

template<size_t k> void increment(size_t* v, size_t& i){ v[k] = i * i++; }

int main(){
    constexpr std::size_t N = 10;
    std::size_t v[N];

    [&v, i = std::size_t{}]<std::size_t... k>(std::index_sequence<k...>) mutable
    {
        (increment<k>(v, i), ...);
    }(std::make_index_sequence<N>{});

    for(std::size_t k = 0; k < N; ++k){ std::cout << v[k] << " , "; }
}
英文:

The mutable keyword can be used to allow a lambda expression to modify objects iT captures by value.

You also need to capture v by reference or increment will be called on a copy of v and have no visible effect.

Live example : https://godbolt.org/z/4xbPe4MdP

#include &lt;iostream&gt;
#include &lt;memory&gt;

template&lt;size_t k&gt; void increment(size_t* v, size_t&amp; i){ v[k]=i*i++; }

int main(){
    constexpr std::size_t N = 10;
    std::size_t v[N];

    [&amp;v,i = std::size_t{}]&lt;std::size_t... k&gt;(std::index_sequence&lt;k...&gt;) mutable
    {
        (increment&lt;k&gt;(v,i), ...);
    }(std::make_index_sequence&lt;N&gt;{});
    
    for(std::size_t k=0;k&lt;N;++k){ std::cout &lt;&lt; v[k] &lt;&lt; &quot; , &quot;; }
}

huangapple
  • 本文由 发表于 2023年5月6日 20:31:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76188903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定