• [Effective Modern C++] Item 3. Understand decltype


    条款三 了解decltype

    基础知识

    提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪。

    以下是一些简单的推断类型:

    const int i = 0; // decltype(i) -> const int
    bool f(const Widget& w); // decltype(w) -> const Widget&, decltype(f) -> bool(const Widget&)
    struct Point {
        int x, y;
    } // decltype(Point::x) -> int
    Widget w; // decltype(w) -> Widget
    if(f(w)); // decltype(f(w)) -> bool
    template<typename T>
    class vector {
    public:
        T& operator[](std::size_t index);
    };
    vector<int> v; // decltype(v) -> vector<int>
    if(v[0] == 0); // decltype(v[0]) -> int&

    在C++11中,decltype的主要作用是推断根据形参类型推断返回类型。

    对于std::vector<bool>,operator[]返回的并不是bool&,而是一个新的对象。

    一种返回类型的推断的用法:

    template<typename Container, typename Index>
    auto authAndAccess(Container& c, Index i) -> decltype(C[i]){
        authenticateUser();
        return c[i];
    }

    C++11允许允许单语句lambda返回类型的推断,C+14扩展到所有lambda和函数。

    // C++14版本,但是会有问题
    template<typename Container, typename Index>
    auto authAndAccess(Container& c, Index i){
        authenticateUser();
        return c[i];
    }

    以上函数虽然使用了auto,但套用auto的规则会出问题。如以上c[i]返回int&,但是根据推断规则会去掉引用类型,造成不能修改。

    以下代码可以正确返回类型:

    // C++14版本,可以正确返回类型
    template<typename Container, typename Index>
    decltype(auto) authAndAccess(Container& c, Index i){
        authenticateUser();
        return c[i];
    }

    auto与decltype(auto)的区别:

    Widget w;
    const Widget& cw = w;
    auto myWidget1 = cw; // myWidget1 -> Widget
    decltype(auto) myWidget2 = cw; // myWidget2 -> const Widget&

    为了使得函数可以同时传入左值和右值,函数引入通用引用,正确形式如下:

    // final C++14 version
    template<typename Container, typename Index>
    decltype(auto) authAndAccess(Container&& c, Index i){
        authenticateUser();
        return std::forward<Container>(c)[i];
    }
    
    // final C++1 version
    template<typename Container, typename Index>
    auto authAndAccess(Container&& c, Index i)
    -> decltype(std::forward<Container>(c)[i]){
        authenticateUser();
        return std::forward<Container>(c)[i];
    }

    在使用decltype时,变量外加上括号会改变推断类型:

    int x = 0;
    decltype(x); // -> int
    decltype((x)); // -> int&

    总结

    • decltype总是产生没经过修改的变量或表达式的类型
    • 对于类型为T的左值表达式而非变量名,decltype总是返回T&类型
    • C++14支持decltype(auto),其就像auto一样从初始化中推断类型,但是使用decltype的来推断类型
  • 相关阅读:
    (八)CXF之用spring添加拦截器
    (七)CXF之与spring整合发布web服务
    (六)CXF之自定义拦截器
    借鉴mini2440的usb-wifi工具集在Beagleboard上移植无线网卡
    ubuntu设置网络
    mysql优化学习
    java日期转化
    Navicat使用
    (转载)windows下mysql忘记密码
    java读取文件乱码
  • 原文地址:https://www.cnblogs.com/Azurewing/p/4727735.html
Copyright © 2020-2023  润新知