![](/img/trans.png)
[英]How can I require (in a C++20 concept) that a type T be a reference to a floating point type?
[英]How can you require that a concept parameter is a reference `&` type?
在下面的概念实现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));
}
首先,没有理由写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))
。 如果消费者特别需要原始范围,这是有问题的。 如果他们只需要一个范围,这很好用。 或者,而不是迭代器,传递一个不绑定到原始源的索引。 如果消费者只在随机访问范围内操作,这会使复制问题减少(只是费用),但如果消费者需要在较弱的范围内操作,这可能是不可接受的费用。
您不能(合理地)检测是否采用参考参数。 但是您可以检测它是否可以采用右值:
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>;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.