以下函数无法编译(ISO C++ 17标准,Visual Studio 2019)
namespace std
{
// Find the first item which matches the predicate. Returns a default constructed item (probably nullptr) on failure.
template <class Container, typename Predicate, typename T = typename std::iterator_traits<Container::iterator>::value_type>
T find_first_or_default(const Container& container, Predicate predicate, T defaultVal = T())
{
auto it = std::find_if(container.begin(), container.end(), predicate);
if (it == container.end())
return defaultVal;
return *it;
}
};
void Test()
{
std::vector<int> vec = { 1,2,3 };
int i = std::find_first_or_default(vec, [](int val) {return val % 2 == 0; });
}
如果我将命名空间更改为'std'以外的任何名称,它都可以编译。我假设std名称空间中的其他东西使模板推导失败。
以下是错误:
Error C2783 'T std::find_first_or_default(const Container &,Predicate,T)': could not deduce template argument for 'T'
Error C2672 'std::find_first_or_default': no matching overloaded function found
1条答案
按热度按时间9jyewag01#
正如注解中提到的,不允许向
std
名称空间添加任何附加符号,只有在显式允许时才专门化一些类。你的程序是病态的,但这不是它无法编译的原因。在:
::iterator
依赖于Container
模板参数,因此除非消除歧义,否则它将被解释为静态数据成员。那么替换将失败,T
无法推导,并且您无法调用该函数。要解决这个问题,请使用typename
消歧器:如果你经常编写这样的代码,定义一个类似于
std::ranges::range_value_t
的方便别名也是有意义的: