是否可以知道参数是否默认
Is it possible to know if the parameter was defaulted
注意:此问题仅限于 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
,该参数编码它是从哪个重载调用的。
一般来说,我建议谨慎使用默认参数并更喜欢函数重载,因为它可以让您更好地控制并且通常还可以提供更好(不那么令人惊讶)的接口。
Is it possible to differ between those two calls for the function?
没有。可以检查vector是否为空,否则没法区分。
您可以做一些聪明的事情,例如传递一个可以转换的实用程序 class,但这不是万无一失的,而且大多毫无意义,因为您可以更轻松地进行两个不同的函数重载。
I have this function signature:
void do_somthing(std::vector<foo>& bar=std::vector<foo>{});
此无法编译,除非使用危险的非标准编译器设置,您应该远离。
特别是,如果未指定 /Za
,Visual C++ 允许这样做,但使用 /W4
仍会产生如下警告:
Whosebug.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
]
Whosebug.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
已默认。
无论你打算在这里做什么,你都必须找到一个完全不同的解决方案。
注意:此问题仅限于 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
,该参数编码它是从哪个重载调用的。
一般来说,我建议谨慎使用默认参数并更喜欢函数重载,因为它可以让您更好地控制并且通常还可以提供更好(不那么令人惊讶)的接口。
Is it possible to differ between those two calls for the function?
没有。可以检查vector是否为空,否则没法区分。
您可以做一些聪明的事情,例如传递一个可以转换的实用程序 class,但这不是万无一失的,而且大多毫无意义,因为您可以更轻松地进行两个不同的函数重载。
I have this function signature:
void do_somthing(std::vector<foo>& bar=std::vector<foo>{});
此无法编译,除非使用危险的非标准编译器设置,您应该远离。
特别是,如果未指定 /Za
,Visual C++ 允许这样做,但使用 /W4
仍会产生如下警告:
Whosebug.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
]
Whosebug.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
已默认。
无论你打算在这里做什么,你都必须找到一个完全不同的解决方案。