概念库提供基础语言概念的定义,它们能用于进行模板实参的编译时校验,以及基于类型属性的函数派发。这些概念在程序中提供等式推理的基础。
标准库中的大多数概念一同加上了语法及语义要求。通常,编译器只能检查语法要求。若在使用点语义要求未得到满足,则程序为病式,不要求诊断。
类型支持(基本类型、RTTI、类型特性)
指定一个类型能隐式转换成另一类型
std::convertible_to
template <class From, class To> concept convertible_to = | (C++20 起) |
概念 convertible_to<From, To> 指定类型和值类别由 From
编码的表达式能隐式和显式转换成 To
类型,而二种转换形式等价。
语义要求
convertible_to<From, To> 仅若符合下列条件才得以实现。给定 From () 类型函数 fun
,满足表达式 fun() 保持相等性(见下方),
- 以下任一成立
To
既非对象亦非到对象引用类型,或- static_cast<To>(fun()) 等于 []() -> To { return fun(); }() ,且
- 下列之一为真:
From
不是到对象引用类型,或From
是到非 const 限定类型的右值引用,而 fun() 所引用的结果状态在上述任一表达式后合法但未指定;或- 上述任一表达式不修改
fun()
所引用的对象。
相等性保持
若表达式对给定的相等输入产生相等输出,则它保持相等性。
- 表达式的输入由其运算数组成。
- 表达式的输出由其结果和表达式所修改的所有运算数(若存在)组成。
进一步要求每个要求保持相等性的表达式都稳定:这种表达式带相同输入对象的二次求值必须拥有相等的输出,而无任何对这些输入对象的显式中间修改。
除非另外提醒,每个用于 requires 表达式中的表达式都要求保持相等性且稳定,而表达式的求值必须只修改其非常运算数。必须不修改常运算数。
参阅
is_convertibleis_nothrow_convertible (C++11)(C++20) | 检查是否能转换一个类型为另一类型 (类模板) |
调用示例 (c++11)
#include <iostream>
#include <type_traits>
class E
{
public:
template<class T> E(T&&) { }
};
class A {};
class B : public A {};
class C {};
class D
{
public:
operator C()
{
return c;
} C c;
};
//自定义的实现
namespace std
{
template <class From, class To>
constexpr bool convertible_to = (std::is_convertible<From, To>::value);
}
int main()
{
std::cout << std::boolalpha;
std::cout << "std::is_convertible<B*, A*>::value: "
<< std::is_convertible<B*, A*>::value << std::endl;
std::cout << "std::is_convertible<A*, B*>::value: "
<< std::is_convertible<A*, B*>::value << std::endl;
std::cout << "std::is_convertible<B*, C*>::value: "
<< std::is_convertible<B*, C*>::value << std::endl;
std::cout << "std::is_convertible<D, C>::value: "
<< std::is_convertible<D, C>::value << std::endl;
std::cout << "std::is_convertible<int, double>::value: "
<< std::is_convertible<int, double>::value << std::endl;
std::cout << "std::is_convertible<int, char>::value: "
<< std::is_convertible<int, char>::value << std::endl;
std::cout << "std::is_convertible<std::string, char>::value: "
<< std::is_convertible<std::string, char>::value << std::endl;
// 完美转发构造函数使类能从任何类型转换
std::cout << "std::is_convertible<A, E>::value: "
<< std::is_convertible<A, E>::value << std::endl;
std::cout << "-----------------------------------------------" << std::endl;
std::cout << std::endl;
std::cout << "std::convertible_to<B, A>: "
<< std::convertible_to<B, A> << std::endl;
std::cout << "std::convertible_to<A, B>: "
<< std::convertible_to<A, B> << std::endl;
std::cout << "std::convertible_to<B*, A*>: "
<< std::convertible_to<B*, A*> << std::endl;
std::cout << "std::convertible_to<A*, B*>: "
<< std::convertible_to<A*, B*> << std::endl;
std::cout << "std::convertible_to<B*, C*>: "
<< std::convertible_to<B*, C*> << std::endl;
std::cout << "std::convertible_to<D, C>: "
<< std::convertible_to<D, C> << std::endl;
std::cout << "std::convertible_to<int, double>: "
<< std::convertible_to<int, double> << std::endl;
std::cout << "std::convertible_to<int, char>: "
<< std::convertible_to<int, char> << std::endl;
std::cout << "std::convertible_to<std::string, char>: "
<< std::convertible_to<std::string, char> << std::endl;
// 完美转发构造函数使类能从任何类型转换
std::cout << "std::convertible_to<A, E>: "
<< std::convertible_to<A, E> << std::endl;
return 0;
}
输出
std::is_convertible<B*, A*>::value: true
std::is_convertible<A*, B*>::value: false
std::is_convertible<B*, C*>::value: false
std::is_convertible<D, C>::value: true
std::is_convertible<int, double>::value: true
std::is_convertible<int, char>::value: true
std::is_convertible<std::string, char>::value: false
std::is_convertible<A, E>::value: true
-----------------------------------------------
std::convertible_to<B, A>: true
std::convertible_to<A, B>: false
std::convertible_to<B*, A*>: true
std::convertible_to<A*, B*>: false
std::convertible_to<B*, C*>: false
std::convertible_to<D, C>: true
std::convertible_to<int, double>: true
std::convertible_to<int, char>: true
std::convertible_to<std::string, char>: false
std::convertible_to<A, E>: true