在 C++ 中处理可选 parameters/default 值的最佳方法
Best way to approach optional parameters/default value in C++
我想知道是否有一种方法可以执行以下操作,所有操作都具有一个功能:
template <typename T>
void _class_<T>::func (T chgx = x, T chg y = y, T chgz = z)
{
x = chgx;
y = chgy;
z = chgz;
}
我想做的是将默认值设置为我想要更改的值,这样一来,如果我省略一些参数,这些值 就不会 变了。上面的代码不起作用,我想我明白为什么(该函数实际上无法访问这些值,因此会引发错误)。
我想知道是否有办法像我上面描述的那样,只用一种功能。我唯一的选择是用多个定义重载函数来处理不同数量的参数吗?
您可以通过一组重载函数来完成您想要的。
// First overload. Needs all arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy, T chgz)
{
x = chgx;
y = chgy;
z = chgz;
}
// Second overload. Needs two arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy)
{
x = chgx;
y = chgy;
}
// Third overload. Needs one argument.
template <typename T>
void _class_<T>::func (T chgx)
{
x = chgx;
}
// You can have a fourth overload that takes no arguments.
// However, it's totally useless.
template <typename T>
void _class_<T>::func ()
{
// Nothing needs to be changed.
}
一些重复代码较少的东西(感谢@BenVoigt 的建议):
// Second overload. Needs two arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy)
{
func(chgx, chgy, z);
}
// Third overload. Needs one argument.
template <typename T>
void _class_<T>::func (T chgx)
{
func(chgx, y);
}
// You can have a fourth overload that takes no arguments.
// However, it's totally useless.
template <typename T>
void _class_<T>::func ()
{
func(x);
}
一种方法是使用 boost::optional
,它是一个小型包装器,如果没有给它提供参数则默认为空:
using boost::optional;
template<typename T>
void _class_<T>::func( optional<T> cx = {},
optional<T> cy = {}, optional<T> cz = {} )
{
if ( cx ) x = *cx;
if ( cy ) y = *cy;
if ( cz ) z = *cz;
}
虽然这样做你不会得到移动或引用语义(所以我仍然更喜欢 R Sahu 的解决方案)
一种方法(同样,不支持移动或引用语义)是使函数通过初始化列表接受可变参数:
template<typename T>
void _class_<T>::func( std::initializer_list<T> items )
{
T const *ptr = items.begin();
if ( ptr != items.end() ) x = *ptr++;
if ( ptr != items.end() ) y = *ptr++;
if ( ptr != items.end() ) z = *ptr++;
}
用法:
obj.func({ 1, 2, 3 });
obj.func({ 1 });
obj.func({});
我想知道是否有一种方法可以执行以下操作,所有操作都具有一个功能:
template <typename T>
void _class_<T>::func (T chgx = x, T chg y = y, T chgz = z)
{
x = chgx;
y = chgy;
z = chgz;
}
我想做的是将默认值设置为我想要更改的值,这样一来,如果我省略一些参数,这些值 就不会 变了。上面的代码不起作用,我想我明白为什么(该函数实际上无法访问这些值,因此会引发错误)。
我想知道是否有办法像我上面描述的那样,只用一种功能。我唯一的选择是用多个定义重载函数来处理不同数量的参数吗?
您可以通过一组重载函数来完成您想要的。
// First overload. Needs all arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy, T chgz)
{
x = chgx;
y = chgy;
z = chgz;
}
// Second overload. Needs two arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy)
{
x = chgx;
y = chgy;
}
// Third overload. Needs one argument.
template <typename T>
void _class_<T>::func (T chgx)
{
x = chgx;
}
// You can have a fourth overload that takes no arguments.
// However, it's totally useless.
template <typename T>
void _class_<T>::func ()
{
// Nothing needs to be changed.
}
一些重复代码较少的东西(感谢@BenVoigt 的建议):
// Second overload. Needs two arguments.
template <typename T>
void _class_<T>::func (T chgx, T chgy)
{
func(chgx, chgy, z);
}
// Third overload. Needs one argument.
template <typename T>
void _class_<T>::func (T chgx)
{
func(chgx, y);
}
// You can have a fourth overload that takes no arguments.
// However, it's totally useless.
template <typename T>
void _class_<T>::func ()
{
func(x);
}
一种方法是使用 boost::optional
,它是一个小型包装器,如果没有给它提供参数则默认为空:
using boost::optional;
template<typename T>
void _class_<T>::func( optional<T> cx = {},
optional<T> cy = {}, optional<T> cz = {} )
{
if ( cx ) x = *cx;
if ( cy ) y = *cy;
if ( cz ) z = *cz;
}
虽然这样做你不会得到移动或引用语义(所以我仍然更喜欢 R Sahu 的解决方案)
一种方法(同样,不支持移动或引用语义)是使函数通过初始化列表接受可变参数:
template<typename T>
void _class_<T>::func( std::initializer_list<T> items )
{
T const *ptr = items.begin();
if ( ptr != items.end() ) x = *ptr++;
if ( ptr != items.end() ) y = *ptr++;
if ( ptr != items.end() ) z = *ptr++;
}
用法:
obj.func({ 1, 2, 3 });
obj.func({ 1 });
obj.func({});