说明
c++ templates学习中会遇到大量的模版常用函数,书上不会详细介绍,查看一个之后要永久记录一段时间之后再看看,这里总结一下。
undeclared();
undeclared();//若undeclared();未定义,则在第一阶段编译时报错
undeclared(t);//若t未知,则在第二编译阶段报错
第一阶段在模板定义时进行,检查与类型参数无关的错误,如未定义的符号等;第二阶段在模板实例化时进行,检查与类型参数相关的错误。因此,编译器需要在定义阶段就进行函数查找,以确保模板定义的正确性。
std::decay<T>
在<type_traits>定义,将T类型转换为它的衰变类型。例如去const、去&、去易变性限定符、数组变为*。
#include <type_traits>
#include <iostream>
template<typename T1,typename T2>
auto max(T1 a, T2 b)->typename std::decay<decltype(true ? a : b)>::type
{
return a > b ? a : b;
}
template<typename T>
void fun(T&& t)
{
//我们希望创建与参数同类型的,而不是引用
typedef typename std::decay<T>::type U;
U u;
//x与t的原始类型相同
typename std::decay<T>::type x = t;
}
enum Enuma
{
type1,
type2
};
class Type{};
void main()
{
//类型都是int
std::decay<int&&>::type a;
std::decay<int&>::type b;
std::decay<const int>::type c;
std::decay<volatile int>::type d;
//降级为int*
std::decay<int[10]>::type e;
//void(*)()
std::decay<void()>::type f;
//enum、class类型
std::decay<const Enuma>::type g;
std::decay<const Type&>::type h;
a = 1;
}
std::remove_reference_t<T> //移除引用
std::remove_cv_t<T>//移除const或volatile
auto初始化是衰变的,
decltype不会衰变。
decltype
不是函数,是关键字。查询声明类型或表达式类型。
const int a = 1;
decltype(a) b = 2;//const int
auto返回值使用会降级,
decltype不会降级,需要指定类型
decltype(auto)可在返回值类型中使用,表示不降级的auto。
std::common_type<typename... T>
函数返回值的类型可以转换的类型。
确定所有类型 T... 的共用类型,即所有 T... 都能隐式转换到的类型。若这种类型(根据后述规则确定)存在,则成员 type 指名该类型。否则,无成员 type 。
#include <type_traits>
#include <iostream>
template<typename T,typename U>
typename std::common_type<T, U>::type max(T t, U u)
{
return t > u ? t : u;
}
enum Enuma
{
type1,
type2
};
class Type{};
void main()
{
auto a = max(1, 2.1);//dobule
auto b = max(2, 1.1);//double
std::cout<< max(1, 2.1)<<std::endl;//2.1
std::cout<< max(2, 1.1);//2
a = 1;
}
#include <iostream>
#include <type_traits>
struct Base {};
struct Derived : Base {};
int main(int argc, char** argv)
{
{
typedef std::common_type<char, short, int>::type A;
typedef std::common_type<float, double>::type B;
typedef std::common_type<Derived, Base>::type C;
typedef std::common_type<Derived*, Base*>::type D;
typedef std::common_type<const int, volatile int>::type E;
std::cout << std::boolalpha;
std::cout << "typedefs of int:" << std::endl;
std::cout << "A: " << std::is_same<int, A>::value << std::endl;
std::cout << "B: " << std::is_same<int, B>::value << std::endl;
std::cout << "C: " << std::is_same<int, C>::value << std::endl;
std::cout << "D: " << std::is_same<int, D>::value << std::endl;
std::cout << "E: " << std::is_same<int, E>::value << std::endl;
}
{
typedef std::common_type_t<char, short, int> A;
typedef std::common_type_t<float, double> B;
typedef std::common_type_t<Derived, Base> C;
typedef std::common_type_t<Derived*, Base*> D;
typedef std::common_type_t<const int, volatile int> E;
std::cout << std::boolalpha;
std::cout << "typedefs of int:" << std::endl;
std::cout << "A: " << std::is_same_v<int, A> << std::endl;
std::cout << "B: " << std::is_same_v<int, B> << std::endl;
std::cout << "C: " << std::is_same_v<int, C> << std::endl;
std::cout << "D: " << std::is_same_v<int, D> << std::endl;
std::cout << "E: " << std::is_same_v<int, E> << std::endl;
}
return 0;
}
输出:
typedefs of int:
A: true
B: false
C: false
D: false
E: true
typedefs of int:
A: true
B: false
C: false
D: false
E: true
std::is_same<T1,T2>
如果 T
与 U
指名同一类型(考虑 const/volatile 限定),那么成员常量 value
等于 true。
auto b=std::is_same<int, const int>::value;//false//is_same<>不降级
auto b1 = std::is_same<int,std::uint8_t>::value;//false//类型int不相同
constexpr
提供在编译时计算某些值的能力。
template<typename T1,typename T2>
constexpr auto max(T1 a,T2 b)
{
return a>b?a:b;
}
int a[::max(sizeof(int,1000u)];
std::is_default_constructible<T>
T是否有默认的构造函数。
#include <type_traits>
class A {
};
class B {
B() = delete;
};
int main(int argc, char** argv) {
bool b = std::is_default_constructible<A>::value;//true
bool b1 = std::is_default_constructible<B>::value;//false
}
std::add_const<T>, std::add_cv<T>, std::add_volatile<T>
增加const, const volatile, volatile.
#include <iostream>
#include <type_traits>
struct foo
{
void m() { std::cout << "Non-cv\n"; }
void m() const { std::cout << "Const\n"; }
void m() volatile { std::cout << "Volatile\n"; }
void m() const volatile { std::cout << "Const-volatile\n"; }
};
int main()
{
foo{}.m();//Non-cv
std::add_const<foo>::type{}.m();//Const
std::add_volatile<foo>::type{}.m();//Volatile
std::add_cv<foo>::type{}.m();//Const - volatile
}
std::enable_if<bool B,typename T>
如果B为true,则enable_if拥有T::type,否则无该type。
用于函数返回值、函数参数、模板形参。
template <class _First, class... _Rest>
array(_First, _Rest...) ->
array<typename _Enforce_same<_First, _Rest...>::type, 1 + sizeof...(_Rest)>;
std::get<size_t _Idx,class _Ty,size_t _Size>(array&);
提取第I个元素。
std::array<int, 3> a{ 1,2,3 };
int b = std::get<0>(a);
sizeof...()
template<typename T,typename... Types>
void print(T firstArg, Types... args) {
cout << sizeof...(Types) << endl;//不定类型个数
cout << sizeof...(args) << endl;//不定变量个数
}
... op
不定参数操作。
template<typename ...T>
auto foldSum(T... s) {
return (... + s);//这里要加括号
}
int main()
{
cout<<foldSum(1, 2, 3);
}
这个例子属于... op pack.
问题
实参不依赖模板参数
template<typename T>
class Base {
public:
void bar() {
cout << "Base::bar()" << endl;
}
};
template<typename T>
class Derived :public Base<T> {
public:
void foo() {
//bar();//error
//this->bar();//ok1
//Base<T>::bar();//ok2
}
//ok
// using Base<T>::bar;
// void foo1() {
// bar();
// }
};
error的解释:
编译器不会主动查找依赖基类的函数。由于这种查找发生在模板定义阶段,而不是实例化阶段,编译器无法看到依赖基类中的函数。
编译器查找函数只在模版定义阶段,而不在模板实例化阶段,主要基于以下原因:
两阶段检查:模板编译时会进行两阶段检查,第一阶段在模板定义时进行,检查与类型参数无关的错误,如未定义的符号等;第二阶段在模板实例化时进行,检查与类型参数相关的错误。因此,编译器需要在定义阶段就进行函数查找,以确保模板定义的正确性。
避免链接错误:如果在实例化阶段进行函数查找,可能会导致链接错误,因为编译器可能无法在实例化时找到函数的定义。将函数查找放在定义阶段,可以确保在实例化之前就已经找到了所有必要的函数定义,从而避免链接错误。
...补充中