[英]Best way to make both a compile-time and runtime version of a function
[英]Best way to pass compile-time list of values to function?
我試圖找到將值的編譯時列表傳遞給實用程序 function 的最佳方法,作為基於實際用例的練習。 該列表將進行一系列操作,結果值將用於運行時的另一個操作。 以下是我找到的一些解決方案,簡化為 MWE。
當然,實際用例中的操作要復雜得多,因此需要這些實用功能。
template <int number>
constexpr int sum() {
return number;
}
template <int number, int next, int... rest>
constexpr int sum() {
return number + sum<next, rest...>();
}
//API:
template <int... numbers>
inline void add(int& target) {
target += sum<numbers...>();
}
...
int number = 0;
add<1, 2, 3, 4, 5>(number);
優點:
缺點:
std::array
template <size_t N, std::array<int, N> numbers>
constexpr int sum() {
int ret = 0;
for (int number : numbers)
ret += number;
return ret;
}
//API:
template <size_t N, std::array<int, N> numbers>
inline void add(int& target) {
target += sum<N, numbers>();
}
...
int number = 0;
add<5, std::array{1, 2, 3, 4, 5}>(number);
優點:
缺點:
std::array
作為非類型模板參數傳遞std::array
包裝器template <size_t N>
struct IntArray {
constexpr IntArray(std::array<int, N> arr_) : arr(arr_) {}
const std::array<int, N> arr;
};
template <IntArray numbers>
constexpr int sum() {
int ret = 0;
for (int number : numbers.arr)
ret += number;
return ret;
}
//API:
template <IntArray numbers>
inline void add(int& target) {
target += sum<numbers>();
}
...
int target = 0;
add<IntArray<5>({1, 2, 3, 4, 5})>(target);
優點:
缺點:
IntArray
作為非類型模板參數傳遞,並且還能夠在至少 function 定義中省略IntArray
模板參數值std::initializer_list
template <std::initializer_list<int> numbers>
constexpr int sum() {
int ret = 0;
for (int number : numbers)
ret += number;
return ret;
}
template <std::initializer_list<int> numbers>
inline void add(int& target) {
target += sum<numbers>();
}
...
int target = 0;
add<{1, 2, 3, 4, 5}>(target);
優點:
缺點:
gnu++2a
): 'std::initializer_list<int>' is not a valid type for a template non-type parameter because it is not structural
說實話,我不知道“非結構性”是什么意思。 考慮到std::initializer_list
顯然完全是constexpr
並且std::array
在相同的情況下工作,我實際上對這種方法不起作用這一事實感到驚訝和失望。 標准中似乎有一個關於std::initializer_list
字面性的錯誤: https://stackoverflow.com/a/28115954/1525238無論如何,我確實認為這是一些非常酷的編譯的錯失機會-時間魔法。
您能否提出以任何可能的方式改進上述解決方案的任何方法,或提出其他解決方案? 理想情況下,“最佳”解決方案將結合所有 API 和實施清潔度和可讀性,同時要求盡可能低的 c++ 標准。
感謝 HolyBlackCat 建議從包中初始化一個std::array
,我不知道這是可能的:
template <int... numbers>
constexpr int sum() {
std::array<int, sizeof...(numbers)> arr = {numbers...};
int ret = 0;
for(int number : arr)
ret += number;
return ret;
}
//API:
template <int... numbers>
inline void add(int& target) {
target += sum<numbers...>();
}
...
int number = 0;
add<1, 2, 3, 4, 5>(number);
這使得實現更加簡潔。 需要 c++17。
為什么不直接使用 initializer_list 參數呢?
constexpr int sum(std::initializer_list<int> numbers) {
int ret = 0;
for (int number : numbers)
ret += number;
return ret;
}
int target = sum({1, 2, 3, 4, 5});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.