欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中constexpr與函數(shù)參數(shù)轉(zhuǎn)發(fā)的操作方法

 更新時間:2024年02月27日 10:23:01   作者:leapmotion  
constexpr是c++11引入的關鍵字,c++11的constexpr的函數(shù)中只是支持單句代碼,c++14限制放寬,可以在里邊寫循環(huán)及邏輯判斷等語句,本文探討關于constexpr的函數(shù)中參數(shù)的現(xiàn)象,以及如果參數(shù)是constexpr如何做轉(zhuǎn)發(fā),感興趣的朋友一起看看吧

本文和大家探討下關于constexpr的函數(shù)中參數(shù)的現(xiàn)象,以及如果參數(shù)是constexpr如何做轉(zhuǎn)發(fā)

關于constexpr函數(shù)

constexpr是c++11引入的關鍵字,c++11的constexpr的函數(shù)中只是支持單句代碼,c++14限制放寬,可以在里邊寫循環(huán)及邏輯判斷等語句。
constexpr形容函數(shù)表示該函數(shù)被編譯期計算或者調(diào)用。但是只能是可能被編譯期計算,舉例來說:

constexpr int square(int num) {
    return num * num;
}

假設這里有一個計算平方的函數(shù)是constexpr形容,那么我如果這樣調(diào)用:

int main() {
    int val = square(12);
}

我們可以看下編譯后的匯編:

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 144 // 這里
        mov     eax, 0
        pop     rbp
        ret

可以看到main函數(shù)里在運行時根本沒有去調(diào)用square函數(shù),而是在編譯期直接將square函數(shù)計算得出144并賦值。也就是說傳遞參數(shù)是字面量(或者constexpr變量)可以被認定是編譯期調(diào)用。

那么我們?nèi)绻麚Q一種方式調(diào)用呢?

int main() {
    int p = 12;
    int val = square(p);
}

通過參數(shù)傳遞進來,再來看下匯編:

square(int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     eax, DWORD PTR [rbp-4]
        imul    eax, eax
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 12
        mov     eax, DWORD PTR [rbp-4]
        mov     edi, eax
        call    square(int)
        mov     DWORD PTR [rbp-8], eax
        mov     eax, 0
        leave
        ret

略顯復雜,不需要關注很多匯編代碼,我們只需要知道運行時確實會去執(zhí)行square函數(shù)。

constexpr函數(shù)小結

那也就是說constexpr函數(shù)并不是完全是編譯期執(zhí)行,編譯器其實和你傳遞的參數(shù)或者函數(shù)內(nèi)部的一些邏輯來判斷。

constexpr參數(shù)傳遞

這里假設有一個這樣的例子:

// ...
struct AddSum {
    void add(int val) {
        constexpr auto sq = square(val);
        sum += sq;
    }
    int sum = 0;
};
int main() {
    constexpr int p = 12;
    AddSum a;
    a.add(p);
    return 0;    
}

需要把一些編譯期的數(shù)字的平方加起來,在add函數(shù)中使用constexpr來接收square的返回值,因為這樣可以使得square是編譯期執(zhí)行的,不過可惜的是這里不能通過編譯,因為square不能確定val是不是constexpr。但是我們明明傳遞的就是constexpr的變量。那么問題來了,如何在傳參數(shù)的時候能夠?qū)?code>constexpr的屬性進行傳遞呢?

C++并不支持在形參使用constexpr限制:

// error: Function parameter cannot be constexpr
void add(constexpr int val) { 
    // ...
}

且使用完美轉(zhuǎn)發(fā)也不能將constexpr進行傳遞。

template<typename T>
void add(T&& val) {
     constexpr auto sq = square(val); // error
}

使用非類型模板參數(shù)

既然用到了模板,那么我們完全可以將val作為非類型的模板參數(shù)進行傳遞:

template<int val>
void add() {
    constexpr auto sq = square(val);
    sum += sq;
}

如果這里就結束的話,那確實不值得討論了,非類型模板參數(shù)的問題是只能傳遞一些基本類型,我們自定的類constexpr對象則不能傳遞。

值內(nèi)嵌的類型

其實我們可以借助一個helper類,將要傳遞的值封裝在這里類里,然后需要的時候取出來。如下:

struct Helper {
    static constexpr int value() {
        return 12;
    }
};
struct AddSum {
    template<typename H>
    void add(H) {
        constexpr auto sq = square(H::value());
        sum += sq;
    }
    int sum = 0;
};
int main() {
    AddSum a;
    a.add(Helper{});
    return 0;
}

可以看到我們Helper中value用來封裝了要傳遞的int值,然后將Helper的對象傳遞給add,進一步可以獲取到value。

這里不能通用,因為我們需要在helper里寫死這個值,又沒辦法將值傳遞給helper,感覺又繞回來了。哈哈,這里我們使用宏來定義一個通用的模式:

#define CONSTEXPR_HELPER(...)                 \
struct Helper {                               \
    static constexpr decltype(auto) value() { \
        return __VA_ARGS__;                   \
    }                                         \
};
int main() {
    AddSum a;
    using H = CONSTEXPR_HELPER(12);
    a.add(H{});
    return 0;
}

這種情況下就可以使用任意類型的的constexpr屬性進行傳遞了。同時也可以將值在調(diào)用時傳遞而不是寫死。

constexpr的lambda表達式

C++17出現(xiàn)了constexpr形式的lambda表達式,我們可以借助它來實現(xiàn)constexpr的傳遞

struct AddSum {
    template<typename H>
    void add(H h) {
        constexpr auto sq = square(h());
        sum += sq;
    }
    int sum = 0;
};
int main() {
    AddSum a;
    a.add([](){
        return 12;
    });
    return 0;
}

這里我們使用constexpr的lambda對象傳遞給add函數(shù),同時傳遞過來的lambda表達式仍然具有l(wèi)ambda屬性,然后調(diào)用將值獲取到。

這樣也就是在C++17版本不需要使用宏來定義內(nèi)嵌值的類型。

總結

本篇文章就是和大家探討下constexpr的參數(shù)傳遞的問題,可以使用非類型模板參數(shù),宏定義,lambda表達式做到。

感謝大家,點個贊吧~

ref

https://mpark.github.io/programming/2017/05/26/constexpr-function-parameters/

到此這篇關于C++中constexpr與函數(shù)參數(shù)轉(zhuǎn)發(fā)的文章就介紹到這了,更多相關constexpr函數(shù)參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++實現(xiàn)LeetCode(151.翻轉(zhuǎn)字符串中的單詞)

    C++實現(xiàn)LeetCode(151.翻轉(zhuǎn)字符串中的單詞)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(151.翻轉(zhuǎn)字符串中的單詞),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 詳解C語言的結構體中成員變量偏移問題

    詳解C語言的結構體中成員變量偏移問題

    這篇文章主要介紹了C語言的結構體中成員變量偏移問題,以講解如何編寫宏來對成員變量進行修改為主,需要的朋友可以參考下
    2016-04-04
  • 淺析C語言中的數(shù)組及字符數(shù)組

    淺析C語言中的數(shù)組及字符數(shù)組

    這篇文章主要介紹了C語言中的數(shù)組及字符數(shù)組,是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-11-11
  • C++接口文件小技巧之PIMPL詳解

    C++接口文件小技巧之PIMPL詳解

    C++ 里面有一些慣用法(idioms),如 RAII,PIMPL,copy-swap、CRTP、SFINAE 等,今天要說的是 PIMPL,即 Pointer To Implementation,指向?qū)崿F(xiàn)的指針,感興趣的可以了解一下
    2023-06-06
  • C++內(nèi)存四區(qū)之代碼區(qū)、全局區(qū)、棧區(qū)和堆區(qū)

    C++內(nèi)存四區(qū)之代碼區(qū)、全局區(qū)、棧區(qū)和堆區(qū)

    C++編譯器會把代碼直接分為四個小區(qū),弄懂這四小區(qū)對我們理解內(nèi)存有所幫助,所以下面這篇文章主要給大家介紹了關于C++內(nèi)存四區(qū)之代碼區(qū)、全局區(qū)、棧區(qū)和堆區(qū)的相關資料,需要的朋友可以參考下
    2021-07-07
  • C語言如何建立動態(tài)鏈表問題

    C語言如何建立動態(tài)鏈表問題

    這篇文章主要介紹了C語言如何建立動態(tài)鏈表問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • C語言實現(xiàn)BMP圖像閉運算處理

    C語言實現(xiàn)BMP圖像閉運算處理

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)BMP圖像閉運算處理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C語言的可變參數(shù)函數(shù)實現(xiàn)詳解

    C語言的可變參數(shù)函數(shù)實現(xiàn)詳解

    某些情況下我們希望函數(shù)的參數(shù)個數(shù)可以根據(jù)需要確定,因此c語言引入可變參數(shù)函數(shù)。典型的可變參數(shù)函數(shù)的例子有printf()、scanf()等,下面我就開始講解
    2021-08-08
  • C++自定義封裝socket操作業(yè)務類完整實例

    C++自定義封裝socket操作業(yè)務類完整實例

    這篇文章主要介紹了C++自定義封裝socket操作業(yè)務類,結合完整實例形式分析了Linux環(huán)境下C++操作socket的封裝業(yè)務類,可實現(xiàn)基本的socket連接、參數(shù)設置、發(fā)送請求等基本功能,需要的朋友可以參考下
    2017-08-08
  • C++空間命名的使用

    C++空間命名的使用

    本文主要介紹了C++空間命名的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01

最新評論