You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++20中can-reference exposition-only概念直接实现的语法疑问

关于C++20中can-reference exposition-only概念的实现问题

我尝试模仿C++20迭代器概念中的can-reference exposition-only概念,cppreference上的相关代码如下:

template <class I>
concept input_or_output_iterator =
  requires(I i) {
    { *i } -> /*can-reference*/;
  } &&
  std::weakly_incrementable<I>;

最初我通过类型别名实现了相关概念,在Clang 15.0.0下可以正常编译:

/**
 * @brief Alias for defining that a template parameter T is referenceable = T&
 */
template<typename T>
using template_arg_with_ref = T&;

/**
 * @brief satisfied if and only if the type is referenceable (in particular, not void)
 */
template<typename T>
concept can_reference = requires() { typename template_arg_with_ref<T>; };

/**
 * @brief satisfied if and only if the type is dereferenceable (in particular, not void)
 */
template<typename T>
concept dereferenceable = requires(T& t) {
    { *t } -> can_reference;
};

但当我尝试简化代码,不使用类型别名直接定义can_reference概念时:

/**
 * @brief satisfied if and only if the type is referenceable (in particular, not void)
 */
template<typename T>
concept can_reference = requires() { typename T&; };

/**
 * @brief satisfied if and only if the type is dereferenceable (in particular, not void)
 */
template<typename T>
concept dereferenceable = requires(T& t) {
    { *t } -> can_reference;
};

编译器报错:

error: expected ';' at end of requirement
    concept can_reference = requires() { typename T&;; };
                                                   ^
                                                   ;

我想咨询:是否无法直接像上述方式使用T&?还是我只是犯了语法错误,不知道无需类型别名时的正确写法?


问题原因与解决方案

这是C++20 requires表达式的语法限制导致的:

在requires表达式的类型要求(即typename XXX;形式的要求)中,typename后面必须跟一个限定名(qualified name)——比如嵌套类型(T::type)或模板别名实例(template_arg_with_ref<T>),而T&是直接的类型修饰,不属于限定名范畴,因此typename T&;是非法语法,触发编译报错。

无需类型别名的正确实现方式

你可以通过两种方式实现无别名的can_reference概念:

方式1:用表达式要求验证左值引用合法性

通过尝试对T类型对象进行左值引用转换,间接验证T&是否为有效类型:

template<typename T>
concept can_reference = requires(T t) {
    static_cast<T&>(t);
};

方式2:借助标准库模板别名

利用<type_traits>中的std::add_lvalue_reference_t模板别名,它的实例属于合法限定名,可用于类型要求:

#include <type_traits>

template<typename T>
concept can_reference = requires() {
    typename std::add_lvalue_reference_t<T>;
};

两种方式都能达到原代码的效果:判断T是否为可引用类型(即T&合法,排除void等无法被引用的类型)。


内容的提问来源于stack exchange,提问作者Alex Vergara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:35:43