如何select正确的函数重载?
How to select the correct function overload?
在以下情况下 select 正确的函数重载的正确方法是什么?
#include <iostream>
#include <algorithm>
/** the correct overload **/
bool predicate( const char& c )
{
return c == '0';
}
/** the wrong overload **/
template< typename CharType >
bool predicate( const CharType& c, int some_other_parameters )
{
return c == '0';
}
std::string
process_string( const std::string& str )
{
std::string result;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
predicate );
return result;
}
int main()
{
std::cout << process_string("AK0NNDK0ASDAS0") << std::endl;
return 0;
}
您可以使用 lambda 自行解决谓词歧义问题;
std::string
process_string( const std::string& str )
{
std::string result;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
[](char const& c) { return predicate(c); } );
// ^^ use the lambda to call the correct overload
return result;
}
请记住,非模板函数优先于模板函数,这一点也很重要。
或者,您可以转换函数指针(但我认为这更麻烦);
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
static_cast<bool(*)(const char&)>(&predicate) );
Demo.
指针转换的变体包括键入函数指针类型,然后获取指向所需函数的局部变量;
using predicate_t = bool(*)(const char&);
predicate_t my_predicate = &predicate;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
my_predicate );
Demo.
关于哪个选项更好,这取决于样本外部代码的复杂性、它们的位置(即您的代码与第三方代码)、歧义错误的数量、谓词本身。
鉴于 OP 代码中的简单条件,lambda 可以包含测试本身。在这种情况下,lambda 非常简单。
如果计数很高,则更高范围的 using
版本(带有用于指针转换的局部变量)可能是合适的。
如果是 "one time" 问题,static_cast
也没有问题。尽管演员表看起来 "out of place"。
最终,它可能最受个人偏好(或指导方针,如果你有任何涵盖这种情况的指导方针)的影响。
lambda 还可以与更现代的 auto&&
和一些可变参数列表 as seen in this answer in the linked question 结合使用。值得记住的是,这些现代技术非常吻合。在这种情况下,大多数现代编译器也乐观地排除了 lambda,因此使用它没有任何成本(这适用于此处的所有选项,所有选项都只是解决歧义)。
理想情况下,一开始就不应该有歧义,但它确实发生了,我们需要在我们发现它的上下文中以最合适的方式处理它。
在以下情况下 select 正确的函数重载的正确方法是什么?
#include <iostream>
#include <algorithm>
/** the correct overload **/
bool predicate( const char& c )
{
return c == '0';
}
/** the wrong overload **/
template< typename CharType >
bool predicate( const CharType& c, int some_other_parameters )
{
return c == '0';
}
std::string
process_string( const std::string& str )
{
std::string result;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
predicate );
return result;
}
int main()
{
std::cout << process_string("AK0NNDK0ASDAS0") << std::endl;
return 0;
}
您可以使用 lambda 自行解决谓词歧义问题;
std::string
process_string( const std::string& str )
{
std::string result;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
[](char const& c) { return predicate(c); } );
// ^^ use the lambda to call the correct overload
return result;
}
请记住,非模板函数优先于模板函数,这一点也很重要。
或者,您可以转换函数指针(但我认为这更麻烦);
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
static_cast<bool(*)(const char&)>(&predicate) );
Demo.
指针转换的变体包括键入函数指针类型,然后获取指向所需函数的局部变量;
using predicate_t = bool(*)(const char&);
predicate_t my_predicate = &predicate;
std::copy_if( str.begin( ),
str.end( ),
std::back_inserter( result ),
my_predicate );
Demo.
关于哪个选项更好,这取决于样本外部代码的复杂性、它们的位置(即您的代码与第三方代码)、歧义错误的数量、谓词本身。
鉴于 OP 代码中的简单条件,lambda 可以包含测试本身。在这种情况下,lambda 非常简单。
如果计数很高,则更高范围的 using
版本(带有用于指针转换的局部变量)可能是合适的。
如果是 "one time" 问题,static_cast
也没有问题。尽管演员表看起来 "out of place"。
最终,它可能最受个人偏好(或指导方针,如果你有任何涵盖这种情况的指导方针)的影响。
lambda 还可以与更现代的 auto&&
和一些可变参数列表 as seen in this answer in the linked question 结合使用。值得记住的是,这些现代技术非常吻合。在这种情况下,大多数现代编译器也乐观地排除了 lambda,因此使用它没有任何成本(这适用于此处的所有选项,所有选项都只是解决歧义)。
理想情况下,一开始就不应该有歧义,但它确实发生了,我们需要在我们发现它的上下文中以最合适的方式处理它。