我需要为Messages指定一个概念-只要它具有typeTag静态成员,就非常简单-参见下文,我只是写了-如果概念易于理解,我认为我不应该为此写更多的东西使用:
template <typename M>
concept MessageC = requires(M m) {M::typeTag;};
然后我在直接使用时遇到麻烦:
template <MessageC Message>
void send(Message&& m){...}
当推论Message
为Finish&
,其中Finish
实际上是Message
类型时,该概念变得不可用。 Finish&::typeTag
格式错误,因为g ++ 9编译器抱怨。
我可以在概念定义中执行诸如remove_reference之类的操作,除非我不知道这是推荐的方法。是不是C ++ Concept的使用要比这简单?
谢谢。
答案 0 :(得分:2)
最好用这种方式写您的概念:
template<typename M>
concept MessageC = requires { typename M::typeTag; };
即,您需要typename
作为从属名称,requires
表达式中不需要参数。
关于您的实际问题:
template<MessageC Message>
void send(Message&&) {}
等效于:
template<typename Message>
void send(Message&&) requires MessageC<Message> {}
但是,正如您所指出的,Message
是转发引用,可以折叠为左值或右值引用。
因此,您的函数应显示为:
template<typename Message>
void send(Message&&) requires MessageC<std::remove_reference_t<Message>> {}
与语言规则一致。
答案 1 :(得分:1)
除了我不知道这是推荐的方法外,我可以在概念定义中执行诸如remove_reference之类的事情。
标准会执行很多次。它通常不专门针对成员typedef等执行此操作,但这是因为该标准通常使用traits类来获取类型的“成员”,因此可以在这些情况下使用基本类型。指针没有value_type
方法,因此概念库使用iterator/readable_traits
。
概念仍然是C ++;您不能仅仅忽略语言规则。概念中的语句仍然必须遵循C ++的规则。概念的模板参数与其他模板参数一样工作。
答案 2 :(得分:0)
我最终写了以下代码,将typeTag静态值限制在2个字节之内
template <typename M>
concept MessageC = std::remove_reference<M>::type::typeTag >= 0x0
&& std::remove_reference<M>::type::typeTag <= 0xffffu;