[英]Gluing a variadic template to a variadic function
為了繞過GCC在libc ++中未實現的始終內聯的可變參數函數,我想我可以將可變參數函數(如snprintf,更確切地說,* _l變量)包裝在可變參數模板中以實現類似的效果。 實例化將填充可變參數函數的varargs,允許函數很好地內聯。 問題是,我不知道編寫可變參數模板的第一件事,我當然不知道如何將模板參數轉換為單獨的參數。
我想要替換的代碼是以下形式:
int __sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
int __res = vsprintf_l(__s, __l, __format, __va);
va_end(__va);
return __res;
}
我想用以下形式替換:
template<typename... Args>
int __sprintf_l(char *__s, locale_t __l, const char *__format, Args... args) {
int __res = vsprintf_l(__s, __l, __format, args...);
return __res;
}
這是行不通的,因為擴展的args...
無法轉換為type
為va_list {aka char*}
。 如果沒有辦法,我將不得不相信霍華德並實現一個和兩個參數的始終內聯模板,這將有效地使所需代碼的數量翻倍。
編輯:也許一種方法將args
轉換為va_list的std::tuple
可以在這里工作嗎?
我認為你提出的問題令人困惑,所以讓我重申一下。
您希望使用可變參數模板來編寫模擬內聯可變函數的函數。
它無法完成。 va_args
通常被實現為堆棧中第一個參數的void *(注意,為了這個原因,變量函數至少需要有一個非可變參數)。
您需要操縱調用堆棧以獲取正確位置的參數。 現在可能的情況是,可變參數模板函數的參數位於堆棧中與va_args
希望它們在同一位置, va_args
需要模板函數不被內聯。
我強烈懷疑始終內聯可變函數未實現的原因是因為va_args的實現假設標准堆棧布局。 為了使編譯器內聯該函數,它需要分配堆棧空間並復制參數。 它唯一能保存的是實際的jmp
和ret
指令。
它可以做到,但內聯的一半好處蒸發了。 此外,編譯器必須將參數傳遞代碼(編譯器代碼)提升到更一般的位置,以便與常規函數調用一起使用,作為可變函數的強制內聯。 換句話說,它使控制流程顯着變得復雜,從小到無益。
您可以實現自己的sprintf_l
int __noninlined_sprintf_l(char *__s, locale_t __l, const char *__format, ...) {
va_list __va;
va_start(__va, __format);
int __res = vsprintf_l(__s, __l, __format, __va);
va_end(__va);
return __res;
}
而是打電話給那個
template<typename... Args>
int __sprintf_l(char *__s, locale_t __l, const char *__format, Args... args) {
int __res = __noninlined_sprintf_l(__s, __l, __format, args...);
return __res;
}
template<typename... T>
int
variadic(char* s, locale_t locale, const char* format, T&&... t)
{
return __sprintf_l(s, locale, format, std::forward<T>(t)...);
}
然后調用variadic(s, l, "%d %s", 42, "Hello")
將導致調用__sprintf_l(s, l, "%d %s", 42, "Hello")
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.