【问题标题】:Best way to approach optional parameters/default value in C++在 C++ 中处理可选参数/默认值的最佳方法
【发布时间】:2015-06-05 14:18:49
【问题描述】:

我想知道是否有一种方法可以执行以下操作,全部使用一个功能:

    template <typename T>
void _class_<T>::func (T chgx = x, T chg y = y, T chgz = z)
{
     x = chgx;
     y = chgy;
     z = chgz;
}

我想要做的是将默认值设置为我想要更改的值,这样如果我放弃一些参数,这些值不会改变。上面的代码不起作用,我想我明白为什么(该函数实际上无法访问这些值,因此会引发错误)。

我想知道是否有办法像我上面描述的那样,只用一个功能。我唯一的选择是用多个定义重载函数来处理不同数量的参数吗?

【问题讨论】:

  • 您希望能够省略值吗?或者你可以为 null 传递一个占位符吗?
  • 请发布示例代码,展示您如何考虑使用该函数。
  • @Pradhan 那很好,如果这是唯一可行的方法。我只是想知道这样的事情是否可行。
  • 当你说“那些值没有改变”时,没有从什么改变?如果你不提供参数,那么除非你给它一个默认值,否则没有什么可以告诉它有什么值。
  • @R Sahu 这只是一个简单的模板类,包含三个值(一个向量)。这只是为了教育目的。

标签: c++ default-value optional-parameters


【解决方案1】:

你可以通过一组重载函数来完成你想要的。

// 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);
}

【讨论】:

  • 那会被认为是最干净的方法吗?
  • 代码重复过多。可以根据参数较少的一个来实现每一个,或者根据参数最多的一个来实现每个参数,为省略的参数传递变量默认值。
  • @Isthisathing,这对我来说似乎很干净。如果我知道一种更清洁的方法,我会将其添加到答案中。
  • @BenVoigt,感谢您的提示。
【解决方案2】:

一种方法是使用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 的解决方案)

【讨论】:

    【解决方案3】:

    一种方法(同样,不支持移动或引用语义)是使函数通过初始化列表获取可变参数:

    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({});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-26
      • 1970-01-01
      • 2013-04-17
      • 2011-02-13
      • 2011-07-04
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多