zoukankan      html  css  js  c++  java
  • [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的来推断类型
  • 相关阅读:
    HDU 4833 Best Financing(DP)(2014年百度之星程序设计大赛
    HDU 4832 Chess(DP+组合数学)(2014年百度之星程序设计大赛
    HDU 4718 The LCIS on the Tree(树链剖分)
    HDU 3308 LCIS(线段树)
    HDU 4513 吉哥系列故事——完美队形II(Manacher)
    HDU 4512 吉哥系列故事——完美队形(LCIS)
    人造奇迹——二进制位运算的运用
    UVA 10891 Game of Sum(DP)
    在Liferay 7中如何自定义一个Portlet的toolbar
    如何在Liferay 7中创建一个简单的JSF Portlet
  • 原文地址:https://www.cnblogs.com/Azurewing/p/4727735.html
Copyright © 2011-2022 走看看