C ++概念难用吗?

时间:2019-10-29 00:43:40

标签: c++ c++-concepts

我需要为Messages指定一个概念-只要它具有typeTag静态成员,就非常简单-参见下文,我只是写了-如果概念易于理解,我认为我不应该为此写更多的东西使用:

template <typename M>
concept MessageC = requires(M m) {M::typeTag;};

然后我在直接使用时遇到麻烦:

template <MessageC Message>
    void send(Message&& m){...}

当推论MessageFinish&,其中Finish实际上是Message类型时,该概念变得不可用。 Finish&::typeTag格式错误,因为g ++ 9编译器抱怨。 我可以在概念定义中执行诸如remove_reference之类的操作,除非我不知道这是推荐的方法。是不是C ++ Concept的使用要比这简单? 谢谢。

3 个答案:

答案 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;