C++中constexpr與函數(shù)參數(shù)轉(zhuǎn)發(fā)的操作方法
序
本文和大家探討下關(guān)于constexpr的函數(shù)中參數(shù)的現(xiàn)象,以及如果參數(shù)是constexpr如何做轉(zhuǎn)發(fā)
關(guān)于constexpr函數(shù)
constexpr是c++11引入的關(guān)鍵字,c++11的constexpr的函數(shù)中只是支持單句代碼,c++14限制放寬,可以在里邊寫循環(huán)及邏輯判斷等語句。
constexpr形容函數(shù)表示該函數(shù)被編譯期計算或者調(diào)用。但是只能是可能被編譯期計算,舉例來說:
constexpr int square(int num) {
return num * num;
}假設(shè)這里有一個計算平方的函數(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變量)可以被認(rèn)定是編譯期調(diào)用。
那么我們?nèi)绻麚Q一種方式調(diào)用呢?
int main() {
int p = 12;
int val = square(p);
}通過參數(shù)傳遞進(jìn)來,再來看下匯編:
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略顯復(fù)雜,不需要關(guān)注很多匯編代碼,我們只需要知道運行時確實會去執(zhí)行square函數(shù)。
constexpr函數(shù)小結(jié)
那也就是說constexpr函數(shù)并不是完全是編譯期執(zhí)行,編譯器其實和你傳遞的參數(shù)或者函數(shù)內(nèi)部的一些邏輯來判斷。
constexpr參數(shù)傳遞
這里假設(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的屬性進(jìn)行傳遞呢?
C++并不支持在形參使用constexpr限制:
// error: Function parameter cannot be constexpr
void add(constexpr int val) {
// ...
}且使用完美轉(zhuǎn)發(fā)也不能將constexpr進(jìn)行傳遞。
template<typename T>
void add(T&& val) {
constexpr auto sq = square(val); // error
}使用非類型模板參數(shù)
既然用到了模板,那么我們完全可以將val作為非類型的模板參數(shù)進(jìn)行傳遞:
template<int val>
void add() {
constexpr auto sq = square(val);
sum += sq;
}如果這里就結(jié)束的話,那確實不值得討論了,非類型模板參數(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,進(jìn)一步可以獲取到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屬性進(jìn)行傳遞了。同時也可以將值在調(diào)用時傳遞而不是寫死。
constexpr的lambda表達(dá)式
C++17出現(xiàn)了constexpr形式的lambda表達(dá)式,我們可以借助它來實現(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表達(dá)式仍然具有l(wèi)ambda屬性,然后調(diào)用將值獲取到。
這樣也就是在C++17版本不需要使用宏來定義內(nèi)嵌值的類型。
總結(jié)
本篇文章就是和大家探討下constexpr的參數(shù)傳遞的問題,可以使用非類型模板參數(shù),宏定義,lambda表達(dá)式做到。
感謝大家,點個贊吧~
ref
https://mpark.github.io/programming/2017/05/26/constexpr-function-parameters/
到此這篇關(guān)于C++中constexpr與函數(shù)參數(shù)轉(zhuǎn)發(fā)的文章就介紹到這了,更多相關(guān)constexpr函數(shù)參數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++智能指針shared_ptr與weak_ptr的實現(xiàn)分析
shared_ptr是一個標(biāo)準(zhǔn)的共享所有權(quán)的智能指針,允許多個指針指向同一個對象,定義在 memory 文件中,命名空間為 std,這篇文章主要介紹了C++ 中 shared_ptr weak_ptr,需要的朋友可以參考下2022-09-09
利用C++開發(fā)一個protobuf動態(tài)解析工具
數(shù)據(jù)庫中存儲的protobuf序列化的內(nèi)容,有時候查問題想直接解析查看內(nèi)容。很多編碼在網(wǎng)上很容易找到編解碼工具,但protobuf沒有找到編解碼工具,可能這樣的需求比較少吧,那就自己用C++實現(xiàn)一個,感興趣的可以了解一下2023-01-01
詳解C++中十六進(jìn)制字符串轉(zhuǎn)數(shù)字(數(shù)值)
這篇文章主要介紹了詳解C++中十六進(jìn)制字符串轉(zhuǎn)數(shù)字(數(shù)值)的相關(guān)資料,這里提供兩種實現(xiàn)方法,需要的朋友可以參考下2017-08-08
C++中用指向數(shù)組的指針作函數(shù)參數(shù)
多維數(shù)組名作為函數(shù)參數(shù)傳遞:在二維數(shù)組中,數(shù)組名a是指向首行a[0]的指針,也就是說a=&a[0]; a[0]是指向首元素a[0][0]的指針,也就是說a[0]=&a[0][0]2013-10-10
C++自定義封裝socket操作業(yè)務(wù)類完整實例
這篇文章主要介紹了C++自定義封裝socket操作業(yè)務(wù)類,結(jié)合完整實例形式分析了Linux環(huán)境下C++操作socket的封裝業(yè)務(wù)類,可實現(xiàn)基本的socket連接、參數(shù)設(shè)置、發(fā)送請求等基本功能,需要的朋友可以參考下2017-08-08

