[英]Writing a function using a macro with variable number of arguments
[英]Using variable number of float arguments
我正在嘗試為我的struct Polynomial實現一個靈活的構造函數:
struct Polynomial
{
std::vector<float> coefficients;
size_t degree;
};
多項式的程度是可變的。 我想要的是擁有像這樣的構造函數
Polynomial(float... _coefficients);
我嘗試過variadic模板:
template<float... Args>
Polynomial(Args... args);
但浮動是非類型的,所以我做了:
template<typename... Args>
Polynomial(Args... args);
但是這允許我的系數是任何東西,而不是我想要的。 我知道我可以使用:
Polynomial(size_t _degree, ...);
但它真的不安全。
目前我正在使用:
Polynomial(std::vector<float>);
但這迫使調用如下:
Polynomial P({f1, f2, f3}); // with fn floats
所以我想知道是否有一個很好的方法來做到這一點。
謝謝 !
你可以使用initializer_list
:
#include <vector>
#include <initializer_list>
struct Polynomial {
std::vector<float> coeffs;
std::size_t degree;
Polynomial(std::initializer_list<float> init)
: coeffs{ init }, degree(init.size()) { }
};
int main() {
Polynomial p{ 1, 2, 3. };
}
回答你的問題
我想知道是否有一個很好的方法來做到這一點
是的,我認為你這樣做的方式不僅僅是可以接受的。 甚至你使用它的語法Polynomial P({f1, f2, f3});
根本不是那么丑陋。
此外,使用std::vector
與可變參數一樣高效,對其他人來說更容易理解。
使用可變方法,你會發現難以強制接收的那些類型是float
,但是使用std::vector
你可以控制它
我認為你的方式(矢量參數,或更好的(恕我直言)初始化列表)是一個好方法。
另一種方式(簡單但有缺點)可能是使用縮小來確保Args...
是float
或可以縮小到float
類型。 就像是
struct Polinomial
{
std::vector<double> v;
std::size_t degree;
template <typename ... Args>
Polinomial (Args const & ... args)
: v { float{args}... }, degree { sizeof...(Args) }
{ }
};
舉例來說,這很簡單,也很有效
Polinomial p { 2.3f, 3.5f, 6.7f };
但是你的構造函數不接受整數或double
精度或double
long double
值; 所以
Polinomial p { 2.3f, 3.5f, 6.7 };
// ........................^^^ double, error
Polinomial p { 2.3f, 3.5f, 6 };
// ........................^ int, error
而且可能限制太多了。
您可以使用遞歸模板參數處理。 一般的想法是使用一個私有方法,將第一個參數添加到coefficient
向量並與其他參數一起遞歸,直到它們都被處理完畢:
struct Polynomial
{
template<class...Args>
Polynomial(Args... coeffs) {
init(coeffs...);
degree = coefficients.size() - 1;
}
std::vector<float> coefficients;
size_t degree;
private:
void init(float coeff) {
coefficients.push_back(coeff);
}
template<class...Args> void init(float first, Args...others) {
init(first);
init(others...);
}
};
你有很多選擇。 您可能希望查看std::vector
的構造函數以獲取靈感。 例如,帶有兩個迭代器的模板化構造函數非常靈活:
template<typename T>
Polynomial(T begin, T end) : coefficients(begin, end), degree(coefficients.size()) {}
auto init = std::vector<float>{2.0, 1.0, 4.0};
Polynomial p2{init.begin(), init.end()};
或者你可以像Jodocus建議的那樣采用std::initializer_list<float>
。
你可以有一個帶有任何容器類型的模板化構造函數:
template<typename T>
Polynomial(T container)
: coefficients(begin(container), end(container))
, degree(coefficients.size()) {}
auto init = std::vector<float>{2.0, 1.0, 4.0};
Polynomial p2{init};
現場演示 。
或者您可以提供不同構造函數的組合以滿足不同的需求。
你這樣做是一種“好方法”。 想象一下,調用者希望傳遞100個系數。 如果使用可變參數,則強制調用者執行以下操作:
float c1,c2,c3,....c100;
// init them
Polynomial P(c1, c2, c3,....,c100);
如果我要使用100個系數,我肯定會將它們存儲在一個向量中,將它們傳遞給多項式會相當麻煩:
auto coeffs = std::vector<float>(100);
Polynomial P(coeffs[0],coeffs[1],....,coeffs[100]);
但是,如果您接受一個向量,則調用者可以毫無痛苦地執行這兩個操作:
Polynomial P({c1,c2,c2});
Polynomial P(coeffs);
另一方面,使用std::vector
但不允許不同的容器是任意限制。 接下來更好的方法是接受迭代器,並讓調用者執行:
Polynomial P(coeffs.begin(),coeffs.end());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.