是否可以知道该参数是否是默认的

Is it possible to know if the parameter was defaulted

本文关键字:参数 是否是 默认 是否      更新时间:2023-10-16

注意:此问题仅限于 MSVS

我有这个函数签名:

void do_somthing(std::vector<foo>&  bar={});
是否可以

在函数的这两个调用之间有所不同:

第一:

do_something()

第二:

std::vector<foo> v;
do_something(v);

换句话说,我想要这样的东西:

void do_somthing(std::vector<foo>&  bar={}){
    if(/* bar was defaulted*/){
    }
    else{
    }
}

编辑:实际代码:

template<class Tinput_iterator>
            Tmodel perform_fitting(Tinput_iterator begin_data, Tinput_iterator end_data, std::vector<Tpoint>& inliers = {});

不,不是直接的。默认参数由调用站点的编译器替换,而不提供任何进一步的信息。

但是,有一个简单的解决方案可以实现您想要执行的操作:使用重载而不是默认参数。

namespace detail
{
  void
  do_something_impl(const std::vector<foo>& foos)
  {
    // Do things that always need to be done…
  }
}
void
do_something()
{
  // Do things specific to the no-argument case…
  detail::do_something_impl({});
}
void
do_something(const std::vector<foo>& foos)
{
  // Do things specific to the one-argument case…
  detail::do_something_impl(foos);
}

如果您的逻辑要求您更频繁地分支(而不仅仅是在函数的开头或结尾),则可以将一个额外的布尔参数传递给detail::do_something_impl,该参数对调用它的重载进行编码。

通常,我建议谨慎使用默认参数,并且更喜欢函数重载,因为它可以为您提供更好的控制,并且通常还可以提供更好的(不那么令人惊讶的)接口。

我有这个函数签名:

void do_somthing(std::vector<foo>&  bar=std::vector<foo>{});

不能编译,除非有危险的非标准编译器设置,你应该远离。

特别是,如果未指定/Za,Visual C++ 允许这样做,但 /W4 仍会产生如下警告:

stackoverflow.cpp(6): warning C4239: nonstandard extension used: 'default argument': conversion from 'std::vector<foo,std::allocator<_Ty>>' to 'std::vector<foo,
std::allocator<_Ty>> &'
        with
        [
            _Ty=foo
        ]
stackoverflow.cpp(6): note: A non-const reference may only be bound to an lvalue
void do_somthing(std::vector<foo>&  bar=std::vector<foo>{}){
    if(/* bar was defaulted*/){
    }
    else{
    }
}

即使我们假设您实际上包含了使代码编译的缺失const,答案也是:不,不可能知道bar是否是默认的。

无论你打算在这里做什么,你都必须找到一个完全不同的解决方案。

函数

的这两个调用之间是否可以有所不同?

不。 您可以检查向量是否为空,否则无法区分它们。

你可以

做一些聪明的事情,比如传递一个转换的实用程序类,但这不是万无一失的,而且大多毫无意义,因为你可以更容易地制作两个不同的函数重载。