[英]why does range-v3 yield require default constructor
我試圖理解,由於什么原因,yield函數族要求該類是默認的可構造的?
在以下示例中,僅當CNum具有默認構造函數時,vnums1行才會編譯。 vnums2行不需要默認構造函數。
我使用的是Visual Studio 2017和Range-V3-VS2015。 謝謝!
#include <range/v3/all.hpp>
struct CNum
{
// CNum() = default;
explicit CNum(int num) : m_num(num) {}
int m_num;
};
int main()
{
auto ints = ranges::view::ints(0, 10);
// this compiles only of CNum has a default constructor
auto vnums1 = ints
| ranges::view::for_each([](int num) { return ranges::yield_if(num % 2, CNum(num)); })
| ranges::to_vector;
// this compiles even if CNum does not have a default constructor
auto vnums2 = ints
| ranges::view::remove_if([](int num) { return num % 2 == 0; })
| ranges::view::transform([](int num) { return CNum(num); })
| ranges::to_vector;
return 0;
}
我們剛剛將代碼更改為不需要DefaultConstructible。 git拉,享受。
您需要默認構造函數使用ranges::yield_if
是它使用的機制要求類型是默認可構造的。 如果我們看一下我們的代碼
struct yield_if_fn
{
template<typename V>
repeat_n_view<V> operator()(bool b, V v) const
{
return view::repeat_n(std::move(v), b ? 1 : 0);
}
};
/// \relates yield_if_fn
/// \ingroup group-views
RANGES_INLINE_VARIABLE(yield_if_fn, yield_if)
我們可以看到它調用view::repeat_n
。 看看我們得到的代碼
repeat_n_view<Val> operator()(Val value, std::ptrdiff_t n) const
{
return repeat_n_view<Val>{std::move(value), n};
}
如果我們看看repeat_n_view
我們有
// Ordinarily, a view shouldn't contain its elements. This is so that copying
// and assigning ranges is O(1), and also so that in the event of element
// mutation, all the copies of the range see the mutation the same way. The
// repeat_n_view *does* own its lone element, though. This is OK because:
// - O(N) copying is fine when N==1 as it is in this case, and
// - The element is immutable, so there is no potential for incorrect
// semantics.
struct repeat_n_view
: view_facade<repeat_n_view<Val>, finite>
{
private:
friend range_access;
Val value_;
std::ptrdiff_t n_;
// ...
public:
repeat_n_view() = default;
constexpr repeat_n_view(Val value, std::ptrdiff_t n)
: value_(detail::move(value)), n_((RANGES_EXPECT(0 <= n), n))
{}
constexpr std::size_t size() const
{
return static_cast<std::size_t>(n_);
}
};
我們從評論中看到這是一個設計決策,因為這個設計你需要你的類型是默認的可構造的。 Eric將所需的類型描述為SemiRegular
,記錄為
它需要是默認的可構造的,復制和移動可構造的,並且是可破壞的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.