[英]Unnamed loop variable in range-based for loop?
有什么方法可以在基於范圍的 for 循環中不“使用”循環變量,同時避免編譯器警告它未被使用?
對於上下文,我正在嘗試執行以下操作。 我已經啟用了“將警告視為錯誤”,並且我寧願不要像在某處毫無意義地提及它來強制“使用”變量那樣進行黑客攻擊。
size_t getSize(const std::forward_list &list)
{
size_t count = 0;
for (auto & : list) // compile error, but if i do "auto &i" here, MSVC
// complains (reasonably) that i is unused
{
++count;
}
return count;
}
我知道還有其他方法可以做到這一點,但為了論證,我需要使用基於范圍的 for 循環。
您可以定義一個宏:
#if defined(__GNUC__)
# define UNUSED __attribute__ ((unused))
#elif defined(_MSC_VER)
# define UNUSED __pragma(warning(suppress:4100))
#else
# define UNUSED
#endif
...
for (auto &dummy UNUSED : list)
{
++count;
}
...
它適用於 GCC 和 CLANG(對 MSVC 不太確定……我似乎記得 MSVC 將禁用文件其余部分的警告)。
還:
template<class T> void unused(const T &) {}
...
for (auto &dummy : list)
{
unused(dummy);
++count;
}
...
適用於所有編譯器,不應該有任何開銷( 郵袋:關閉編譯器警告)。
Boost 頭文件<boost/core/ignore_unused.hpp>
(Boost >= 1.56) 出於同樣的目的定義了函數模板boost::ignore_unused()
。
對於 C++11, std::ignore
也是一個不錯的選擇:
{
std::ignore = dummy;
// ...
}
類似問題:
PS C++17似乎獲得了[[maybe_unused]]
屬性來提供聲明未使用變量的標准方法。
您始終可以明確聲明該變量在循環體中保證未使用:
ptrdiff_t size( std::forward_list const& list )
{
ptrdiff_t count = 0;
for( auto& dummy : list )
{
(void) dummy; struct dummy; // Wrap this in a macro if you want.
// Here everybody including compiler knows that dummy isn't used and can't be used.
++count;
}
return count;
}
然而,上面的內容遠不如簡單地使用普通的for
循環那么清楚。
更不用說簡單地調用size
。
我認為出於這個原因使用std::for_each ,就像這樣:
template<typename T>
std::size_t get_size(std::forward_list<T> const& list)
{
std::size_t count = 0;
std::for_each(begin(list), end(list), [&count](T const& ){++count;} );
return count;
}
但是,如果您要獲取任何容器的大小,請使用std::distance
std::size_t count = std::distance(begin(list), end(list) );
一種選擇是利用這樣一個事實,即編譯器在具有非平凡的析構函數時通常不會警告未使用的變量,並編寫一個通用的模板化包裝器來處理您正在迭代的實際值,並返回虛擬對象。 像這樣的東西:
template <class RangeType>
class UnusedRange {
public:
UnusedRange(RangeType& wrapped_range) : wrapped_range_(wrapped_range) {}
// Explicit destructor makes compiler not complain about unused vars.
class UnusedVal { public: ~UnusedVal() {} };
class Iterator {
public:
typedef decltype(((RangeType*)nullptr)->begin()) WrappedIteratorType;
Iterator(WrappedIteratorType wrapped_it) : wrapped_it_(wrapped_it) {}
const Iterator& operator++() { ++wrapped_it_; return *this; }
bool operator!=(const Iterator& other) { return wrapped_it_ != other.wrapped_it_; }
UnusedVal operator*() { return UnusedVal(); }
private:
WrappedIteratorType wrapped_it_;
};
Iterator begin() { return Iterator(wrapped_range_.begin()); }
Iterator end() { return Iterator(wrapped_range_.end()); }
private:
RangeType& wrapped_range_;
};
template <class RangeType>
UnusedRange<RangeType> Unused(RangeType& range) {
return UnusedRange<RangeType>(range);
}
你可以這樣使用它:
for (auto unused : Unused(foo)) { ... }
我看到你用c++11標記了你的問題,但如果你打算有一天切換到c++17,你可以在描述的場景中使用maybe_unused
屬性:
for( const auto &[[maybe_unused]] item : *obj->items() )
Foo( ... );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.