C++ 使用可变数量的浮点参数
我正在尝试为我的结构多项式实现一个灵活的构造函数:C++ 使用可变数量的浮点参数,c++,c++11,templates,variadic-templates,C++,C++11,Templates,Variadic Templates,我正在尝试为我的结构多项式实现一个灵活的构造函数: struct Polynomial { std::vector<float> coefficients; size_t degree; }; 我尝试了可变模板: template<float... Args> Polynomial(Args... args); 但这确实不安全 目前我正在使用: Polynomial(std::vector<float>); 所以我想知道是否有一个好的方法
struct Polynomial
{
std::vector<float> coefficients;
size_t degree;
};
我尝试了可变模板:
template<float... Args>
Polynomial(Args... args);
但这确实不安全
目前我正在使用:
Polynomial(std::vector<float>);
所以我想知道是否有一个好的方法来做到这一点
谢谢大家! 您可以使用:
#包括
#包括
结构多项式{
向量系数;
标准:大小和程度;
多项式(std::初始值设定项\u list init)
:coeffs{init},度(init.size()){}
};
int main(){
多项式p{1,2,3};
}
回答您的问题
我想知道是否有一个好的方法来做到这一点
是的,我认为你这样做是完全可以接受的。甚至是使用它的语法多项式P({f1,f2,f3})代码>一点也不难看
此外,使用std::vector
与变量法一样有效,而且对其他人来说更容易理解
使用可变方法,您会发现很难强制接收到的类型为float
,但是使用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()};
模板
多项式(T begin,T end):系数(begin,end),阶数(系数.size()){}
autoinit=std::vector{2.0,1.0,4.0};
多项式p2{init.begin(),init.end()};
或者您可以按照Jodocus的建议,使用std::initializer\u list
您可以有一个采用任何容器类型的模板化构造函数:
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};
模板
多项式(T容器)
:系数(开始(容器)、结束(容器))
,度(系数.size()){}
autoinit=std::vector{2.0,1.0,4.0};
多项式p2{init};
或者您可以提供不同构造函数的组合以满足不同的需求。您这样做的方式是一种“好方法”。假设调用方希望传递100个系数。如果使用variadics,则会强制调用方执行以下操作:
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]);
另一方面,使用std::vector
但不允许使用不同的容器是一种任意限制。更好的方法是接受迭代器,并让调用方执行以下操作:
Polynomial P(coeffs.begin(),coeffs.end());
可以使用递归模板处理参数。一般的想法是使用一种私有方法,将第一个参数添加到系数
向量中,并与其他参数一起递归,直到它们全部被处理:
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...);
}
};
struct多项式
{
模板
多项式(参数…系数){
初始(系数…);
度=系数。大小()-1;
}
std::向量系数;
大小与程度;
私人:
无效初始值(浮动系数){
系数。推回(系数);
}
模板void init(先浮动,参数…其他){
初始(第一);
初始(其他…);
}
};
我认为你的方法(向量参数,或者更好的是初始化列表)是一个好方法
另一种方法(简单但有缺点)是使用缩小,以确保arg…
是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) }
{ }
};
但您的构造函数不接受整数或double
或长double
值;所以
Polinomial p { 2.3f, 3.5f, 6.7 };
// ........................^^^ double, error
Polinomial p { 2.3f, 3.5f, 6 };
// ........................^ int, error
而且可能限制性太强了。“但这会迫使通话像”。。。这有什么不对?对于调用者来说,接受向量比接受变量更灵活。如果用户输入任意系数会发生什么?为什么构造函数多项式p{1,2,3.}代码>不需要()
。只是问一下,我从来没有见过这种情况。@另外,这是统一初始化,它是在C++11中添加的。您可以查阅C++引用的所有初始化规则,包括具有<代码>初始化列表列表> /COD>构造函数的特性。谢谢,我将用@ Max 66解决方案检查差异。我想我会保留这三种方法谢谢你的回答,这是我试图做的,但实际上可能会限制我,我会看看我是否需要其他类型,但目前我认为这将是足够的
auto coeffs = std::vector<float>(100);
Polynomial P(coeffs[0],coeffs[1],....,coeffs[100]);
Polynomial P({c1,c2,c2});
Polynomial P(coeffs);
Polynomial P(coeffs.begin(),coeffs.end());
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...);
}
};
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 };
Polinomial p { 2.3f, 3.5f, 6.7 };
// ........................^^^ double, error
Polinomial p { 2.3f, 3.5f, 6 };
// ........................^ int, error