c++概念生命和类型别名声明
C++ concepts lite and type alias declaration
是否可以使用typedef
或using
在概念内声明类型别名,如概念TS所建议的?如果我尝试下面的MWE,代码无法编译(使用gcc 6.2.1和-fconcepts
开关)
#include <type_traits>
template<typename T>
concept bool TestConcept ()
{
return requires(T t)
{
using V = T;
std::is_integral<V>::value;
};
}
int main()
{
return 0;
}
产生的错误:
main.cpp: In function ‘concept bool TestConcept()’:
main.cpp:8:9: error: expected primary-expression before ‘using’
using V = T;
^~~~~
main.cpp:8:9: error: expected ‘}’ before ‘using’
main.cpp:8:9: error: expected ‘;’ before ‘using’
main.cpp:4:14: error: definition of concept ‘concept bool TestConcept()’ has multiple statements
concept bool TestConcept ()
^~~~~~~~~~~
main.cpp: At global scope:
main.cpp:11:1: error: expected declaration before ‘}’ token
}
^
No。根据TS概念,需求是:
需求:
,,, simple-requirement
,,, 要求
,,, compound-requirement
,,, nested-requirement
其中简单需求是一个表达式后面跟着一个;
, 类型需求是类似typename T::inner
的东西。另外两个听起来和名字一样。
类型别名是声明,而不是表达式,因此不满足需求的要求。
这对我来说是不必要的限制。您知道是否存在一种合理的解决方法,而不是一遍又一遍地编写相同的复杂类型吗?
您可以将约束的实现推迟到另一个概念,将这些类型作为模板参数传递:
template<typename Cont, typename It, typename Value>
concept bool InsertableWith = requires(Cont cont, It it, Value value) {
// use It and Value as much as necessary
cont.insert(it, std::move(value));
};
template<typename Cont>
concept bool Insertable = requires {
// optional
typename Cont::const_iterator;
typename Cont::value_type;
} && InsertableWith<Cont, typename Cont::const_iterator, typename Cont::value_type>;
如果你正在考虑这样做,我建议你在做决定之前先在简单的例子上尝试一下。如何编写概念和约束决定了编译器将如何报告错误,当然,良好的错误是使概念有用的重要组成部分。让我的概念更容易写,同时让错误更难以理解,这不是我可以轻易取舍的。
例如,这就是为什么我冗余地添加typename Cont::const_iterator;
作为显式约束。这使编译器有机会报告此类型需求。在选择InsertableWith
作为概念名称时,我也很小心:我本可以轻松地使用detail::Insertable
,但同时涉及Insertable
和detail::Insertable
的错误可能会更加令人困惑。
最后请注意,这一切都依赖于编译器实现的质量,所以我暂时不期望任何方法是确定的。
- 继承模板类中的类型别名
- 为什么 GCC 在使用类型别名时处理 const reinterpret_cast不同?
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 如何使用类型别名从模板化类中隐藏模板列表
- 如何检测类型类型别名?
- C++类型别名,其中值被替换
- 如何为流输出运算符提供重载<<模板'using'类型别名?
- 通过类型别名从构造函数转发模板推导
- C++中的严格别名规则和类型别名
- 使用其他模板类型参数作为要在函数签名中使用的类型别名声明
- 什么是C++中的类型别名?
- 如何在不违反类型别名规则的情况下解释消息负载?
- 在模板派生类中继承具有类型别名的构造函数
- 类型别名允许分配任意指针,尽管 int* 是必需的
- 使用类型别名,例如使用 A = int(int)
- 模板类函数指针类型别名
- 类型别名和类似类型
- 泛型类型别名,它们彼此不兼容
- 具有类型别名的循环依赖项
- 为什么模板引用类型不能用作模板类型别名参数?