C++;11无循环变量的循环基于范围 在C++中,我需要迭代一定次数,但不需要迭代变量。例如: for( int x=0; x<10; ++x ) { /* code goes here, i do not reference "x" in this code */ }
但是上面给出了一个“未引用的局部变量”,因为我从来没有明确引用过xC++;11无循环变量的循环基于范围 在C++中,我需要迭代一定次数,但不需要迭代变量。例如: for( int x=0; x<10; ++x ) { /* code goes here, i do not reference "x" in this code */ },c++,c++11,C++,C++11,但是上面给出了一个“未引用的局部变量”,因为我从来没有明确引用过x 我想知道是否有一种更优雅的方法来编写上述for循环,这样代码就不会生成“未引用的局部变量”警告。可能有一种方法可以做到这一点,但我非常怀疑它是否更优雅。第一个循环中的内容已经是正确的方法,限制了循环变量的作用域/生命周期 我只会忽略未使用的变量警告(毕竟,这只是编译器可能出错的指示),或者使用编译器工具(如果可用)简单地在该点关闭警告 根据您的环境,使用某种类型的#pragma,或者某些实现允许您执行以下操作: for (int
我想知道是否有一种更优雅的方法来编写上述for循环,这样代码就不会生成“未引用的局部变量”警告。可能有一种方法可以做到这一点,但我非常怀疑它是否更优雅。第一个循环中的内容已经是正确的方法,限制了循环变量的作用域/生命周期 我只会忽略未使用的变量警告(毕竟,这只是编译器可能出错的指示),或者使用编译器工具(如果可用)简单地在该点关闭警告 根据您的环境,使用某种类型的
#pragma
,或者某些实现允许您执行以下操作:
for (int x = 0; x < 10; ++x) {
(void)x;
// Other code goes here, that does not reference "x".
}
for(int x=0;x<10;++x){
(无效)x;
//其他代码在这里,不引用“x”。
}
我已经看到了
void
技巧用于函数体中未使用的参数。现在编辑,声明的循环变量减少了100%
template <typename F>
void repeat(unsigned n, F f) {
while (n--) f();
}
或
或
假设
10
是一个编译时常量,请查看它live at
#include <cstddef>
#include <utility>
template<std::size_t N>
struct do_N_times_type {
template<typename Lambda>
void operator()( Lambda&& closure ) const {
closure();
do_N_times_type<N-1>()(std::forward<Lambda>(closure));
}
};
template<>
struct do_N_times_type<1> {
template<typename Lambda>
void operator()( Lambda&& closure ) const {
std::forward<Lambda>(closure)();
}
};
template<>
struct do_N_times_type<0> {
template<typename Lambda>
void operator()( Lambda&& closure ) const {
}
};
template<std::size_t N, typename Lambda>
void do_N_times( Lambda&& closure ) {
do_N_times_type<N>()( std::forward<Lambda>(closure) );
};
#include <iostream>
void f() {
std::cout << "did it!\n";
}
int main() {
do_N_times<10>([&]{
f();
});
}
它使用了一个变量(\uu
),但看起来非常混乱
另一个疯狂的方法是创建一个类似python的生成器。编写一个生成器包装器,它接受一个iterable范围并生成一个函数,该函数在该范围的value\u type
上返回std::optional
我们可以这样做:
auto _ = make_generator( index_range(10) );
while(_()) {
}
这也会创建一个临时变量,甚至更迟钝
我们可以编写一个在生成器上运行的循环函数:
template<typename Generator, typename Lambda>
void While( Generator&& g, Lambda&& l ) {
while(true) {
auto opt = g();
if (!opt) return;
l(*opt);
}
}
但是这在函数中创建了一些临时变量,比上一个更荒谬,并且依赖于C++1y的特性,而C++1y甚至还没有最终确定
我试图创建一个变量较少的方法来重复10次
但事实上,我只是做循环
您几乎可以通过键入x=x来阻止警告代码>
或者写一个函数
template<typename Unused>
void unused( Unused&& ) {}
这应该会抑制警告,并且实际上很容易理解。没有任何方法可以简单地对几个数字进行迭代,从而创建基于范围的工作
C++11基于范围的循环需要一个范围表达式,该表达式可能是:
- 数组或
- 有两个或两个的班级
- 成员函数
begin()
和end()
或
- 可用的免费函数
begin()
和end()
(通过ADL)
除此之外:基于的范围会产生一些开销:
for ( for_range_declaration : expression ) statement
扩展到
range_init = (expression)
{
auto && __range = range_init;
for ( auto __begin = begin_expr,
__end = end_expr;
__begin != __end;
++__begin ) {
for_range_declaration = *__begin;
statement;
}
}
其中,begin_expr和end_expr是通过阵列检查或begin()
/end()
对获得的
我不认为这比一个简单的for循环更“干净”。特别是在性能方面。
没有呼叫,只是一个简单的循环
我能想出的使其更优雅的唯一方法(优雅显然取决于我的意见)是在此处使用大小或无符号类型:
for(size_t x(0U); x<10U; ++x) f();
for(size_t x(0U);x实际上有一种方法可以实现这一点。您只需返回一个std::array
,其长度由您提供的常量指定:
template <int N>
using range = std::array<int, N>;
int main()
{
for (auto x : range<5>())
{
std::cout << "Awesome\n";
}
}
模板
使用range=std::array;
int main()
{
对于(自动x:range())
{
std::cout在我看来,您误用了基于范围的循环。当逻辑为“对于集合中的每个元素,请执行某些操作”时,应使用基于范围的循环。因为索引变量并不重要,所以整个想法是去掉它。如果你有一个集合,你应该用必要的API对它进行检测,以启用基于范围的迭代。如果你没有集合,你就没有必要使用基于范围的循环(事实上,这是编译器在信息量不大的情况下暗示的)。在这种情况下,正常的for/while循环是自然选择。您可以将STL与lambda表达式一起使用
#include <algorithm>
#include <iostream>
int main() {
int a[] = {1,2,3,4,5,6};
std::for_each(std::begin(a),
std::end(a),
[](int){std::cout << "Don't care" << std::endl;});
}
#包括
#包括
int main(){
int a[]={1,2,3,4,5,6};
标准::对于每个(标准::开始(a),
标准::结束(a),
[](int){std::cout中已经给出了最好的答案:如何定义在整个代码库中使用的未使用的宏,这将抑制此警告。以可移植的方式。这适用于GCC和clang以及任何支持gnu属性的编译器:
for( [[gnu::unused]] auto x : boost::irange(0,10) ) {
并且应该在任何c++11编译器中编译,但如果编译器无法识别gnu属性,则可能不会抑制警告。要参加竞赛:
#include <iostream>
#include <boost/range/irange.hpp>
using namespace std;
using namespace boost;
namespace {
template<typename T> inline void
unused(const T&) {}
}
int main() {
for (auto&& i : irange(0,10)) {
unused(i);
cout << "Something" << endl;
}
return 0;
}
#包括
#包括
使用名称空间std;
使用名称空间boost;
名称空间{
模板内联空
未使用(常数T&){}
}
int main(){
用于(自动和输入:irange(0,10)){
未使用(i);
为了澄清这一点,我的解释是OP正在尝试使用基于范围的for循环来执行此操作。但是,类似于for(auto x:boost::irange(0,10))f();
将发出警告,因为x
未使用。但是变量被引用(在循环条件下)。编译器绝对不应该对该代码发出警告。@rodrigo:我不这么认为,循环条件使用了隐藏的迭代器。x
被写入但从未读取,导致编译器发出警告。@MooingDuckx@Yakk:for(自动x:boost::irange(0,10))
不包含表达式xWhy is 1 special cased?似乎没有必要为什么所有的模板都是魔法?我的答案是3行,并且还将编译为编译时常量n
…(最近在gcc/clang上验证)@谁信任优化器?但说真的,OP要求消除循环变量:所以我认真对待OP。实际上,你应该支持它
template<typename Unused>
void unused( Unused&& ) {}
for(int x{};x<10;++x) {
unused(x);
f();
}
for ( for_range_declaration : expression ) statement
range_init = (expression)
{
auto && __range = range_init;
for ( auto __begin = begin_expr,
__end = end_expr;
__begin != __end;
++__begin ) {
for_range_declaration = *__begin;
statement;
}
}
for(size_t x(0U); x<10U; ++x) f();
template <int N>
using range = std::array<int, N>;
int main()
{
for (auto x : range<5>())
{
std::cout << "Awesome\n";
}
}
#include <algorithm>
#include <iostream>
int main() {
int a[] = {1,2,3,4,5,6};
std::for_each(std::begin(a),
std::end(a),
[](int){std::cout << "Don't care" << std::endl;});
}
for( [[gnu::unused]] auto x : boost::irange(0,10) ) {
#include <iostream>
#include <boost/range/irange.hpp>
using namespace std;
using namespace boost;
namespace {
template<typename T> inline void
unused(const T&) {}
}
int main() {
for (auto&& i : irange(0,10)) {
unused(i);
cout << "Something" << endl;
}
return 0;
}