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
相关产品推荐
相关产品推荐

