在下面的概念實作 struct中String,operator()方法不Source通過參考取值,但仍然滿足概念Consumer。我怎樣才能防止String成為有效的Consumer,特別是通過要求Source source成為參考&?
template <class Type, class Source>
concept Consumer = requires(Type type, Source & source, std::ranges::iterator_t<Source> position) {
{ type.operator()(source, position) } -> std::same_as<Source>;
};
struct String {
public:
std::string operator()(const std::string source, std::string::const_iterator position) {
return "test";
}
};
int main(const int, const char * []) {
String consumer{};
static_assert(Consumer<String, std::string>);
auto test = std::string("test");
consumer(test, std::begin(test));
}
uj5u.com熱心網友回復:
您不能(合理地)檢測是否采用參考引數。但是您可以檢測它是否可以采用右值:
template <class Type, class Source>
concept ConsumerOfRvalue = requires(Type type, Source &&source, std::ranges::iterator_t<Source> position) {
type(std::move(source), position);
};
如果函式&&通過const&、 或 值(假設Source是可移動的)獲取其引數,那么它將滿足ConsumerOfRvalue. 因此,您可以Consumer要求型別不滿足ConsumerOfRvalue:
template <class Type, class Source>
concept Consumer = !ConsumerOfRvalue<Type, Source> &&
requires(Type type, Source & source, std::ranges::iterator_t<Source> position) {
{ type(source, position) } -> std::same_as<Source>;
};
uj5u.com熱心網友回復:
首先,沒有理由寫type.operator()(source, position)。這很奇怪,它只是排除了某些型別的可呼叫物件而沒有任何好處。
在requires-expression中使用“引數”作為參考和值型別之間也沒有區別,除非您要decltype(the_parameter)在正文中的某個地方使用,您可能不會這樣做,因此可以洗掉&.
最后,type對于可呼叫物件來說,這不是一個特別有用的名稱。所以讓我們開始吧:
template <class F, class Source>
concept Consumer = requires (F f, Source source, std::ranges::iterator_t<Source> it) {
{ f(source, it) } -> std::same_as<Source>;
};
好吧,現在你的實際問題:
我怎樣才能防止
String成為有效的Consumer,特別是通過要求Source source成為參考&?
你不能。概念不檢查簽名,它們檢查運算式的有效性,并且它是復制范圍的有效運算式(當然假設它是可復制的)即使這不是您想要發生的事情。請不要開始檢查型別operator()(這會阻止使用多載的函式物件、模板或任何默認引數)。所以一種選擇是處理它。
另一個是傳遞一些f復制不是問題的東西。比如&source…… 這使您的Consumer實作更加尷尬,因為...指標。
另一個是將 API 更改為不太可能被錯誤實作的東西。就像不是傳入(source, it),而是傳入subrange(it, ranges::end(source))。如果消費者特別需要原始范圍,這是有問題的。如果他們只需要一個范圍,這很好用。或者,而不是迭代器,傳遞一個不系結到原始源的索引。如果消費者只在隨機訪問范圍內操作,這會使復制問題減少(只是費用),但如果消費者需要在較弱的范圍內操作,這可能是不可接受的費用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/496795.html
下一篇:從佇列中獲取特定元素
