在下面的概念實作 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
下一篇:從佇列中獲取特定元素