1.auto关键字
auto关键字可以实现自动类型推导,如auto x = 1; auto x = 0.0;被自动推导为int和double类型。在内置类型上似乎并没有什么特别。但在STL容器操作中可大大简化代码。
//------初始代码
std::map<double, double> resultMap;
//...
std::map<double, double>::iterator it = resultMap.begin();
for (; it != resultMap.end(); ++it)
{
//...
}
std::unordered_multimap<int, int> resultMap;
//...
std::pair<std::unordered_multimap<int, int>::iterator, std::unordered_multimap<int, int>::iterator>
range = resultMap.equal_range(key);
//------新语法
std::map<double, double> resultMap;
//...
for (auto it = resultMap.begin(); it != resultMap.end(); ++it)
{
//...
}
std::unordered_multimap<int, int> resultMap;
auto range = map.equal_range(key);
此外,在很多情况下无法知道变量被定义的类型时也可以采用auto关键字。
class A
{
public:
static int get(void)
{
return 0;
}
};
class B
{
public:
static const char* get(void)
{
return "0";
}
};
template <class C>
void func(void)
{
auto val = C::get();//val可根据模版类型传入A或B推导出不同类型
//...
}
2.decltype关键字
auto关键字修饰的变量必须被初始化才能确定所代表类型,即必须定义变量。decltype可以在编译时推导出一个表达式的类型。
语法 decltype(exp)
exp表示一个表达式。类似于sizeof,用来推导表达式的大小。Decltype推导过程在编译期间完成,并不会计算表达式的值。
实际应用:
//------用法1 简化代码
template<class ContainerT>
class Foo
{
typename ContainerT::iterator it_;//可能有问题的一个定义
public:
void func(ContainerT& container)
{
it_ = container.begin();
}
//...
};
{
typedef const std::vector<int> container_t;
container_t arr;
Foo<container_t> foo;
foo.func(arr);//传入报错,应该使用const_iterator
}
//该问题在98/03下只能加一个特化版本
typename ContainerT::const_iterator it_;
void func(const ContainerT& container);
//显然上述定法造成了代码重复,使用decltype可简化
decltype(ContainerT().begin()) it_;
void func(ContainerT& container)
{
it_ = container.begin();
}
//------用法2 变量表达式抽取类型
vector<int> v;
decltype(v)::value_type i = 0;
typedef decltype(nullptr) nullptr_t;//通过编译器关键字定义类型
typedef decltype(sizeof(0)) size_t;
3.auto和decltype结合使用
template<typename R, typename T, typename U>
R add(T t, U u)
{
return t + u;
}
int a = 1; float b = 2.0;
auto c = add<decltype(a + b)>(a, b);//这里decltype<a + b>只是为获取返回值类型
//-------新语法表示1
template <typename T, typename U>
auto add(T t, U u) ->decltype(t + u)//返回类型后置语法
{
return t + u;
}
//-------新语法表示2
//返回类型后置语法解决函数返回值类型依赖于参数而导致难以确定返回值的问题
int& foo(int& i);
float foo(float& f);
template<typename T>
auto func(T& val) -> decltype(foo(val))
{
return foo(val);
}