为什么尽管尝试使用 using 声明将其考虑在内,但仍找不到带有initializer_list参数的函数

问题描述 投票:0回答:1

我正在尝试使用 using 声明来考虑函数:

namespace n {
    struct S {};
    bool equal(S a, S b, std::vector<int> = {1,2}) { return false; }
}
int main() {
    using ::n::equal;
    using ::n::S;
    /// ...
}

只要没有

std::initializer_list
作为第三个参数传递,就可以正常工作

equal(S{},S{});
equal(S{},S{},{1});

但是当

std::initializer_list
作为第三个参数传递时会中断

equal(S{},S{},std::initializer_list<int> {1, 2});

并且只考虑

std::equal

我很难理解为什么这不起作用的原因,并找到一个解决方案来启用这种模式。

现场演示

c++ c++20 initializer-list using-declaration
1个回答
0
投票

我将对这些电话进行编号:

equal(S{},S{});                                    // #1
equal(S{},S{},{1});                                // #2
equal(S{},S{},std::initializer_list<int>{1, 2});   // #3

因此,在

#1
#2
中,唯一可行的候选者是
n::equal
,因此它被调用并且一切正常。

但是在

#3
中,
std::equal
突然成为候选者 - 由于明确的
std::initializer_list
参数,它被 ADL 找到。并且存在
std::equal
的过载,如下所示:

  template<class InputIterator1, class InputIterator2>
    constexpr bool equal(InputIterator1 first1, InputIterator1 last1,
                         InputIterator2 first2);

请注意,虽然模板参数被命名为InputIterator1

InputIterator2
,并且这些类型
确实应该是输入迭代器,但算法本身不受约束,因此它被认为是可行的候选者。

n::equal

std::equal
 之间,后者是更好的匹配 - 所有参数都完全匹配,而对于 
n::equal
 需要从 
std::initializer_list<int>
std::vector<int>
 的显式转换。因此,选择了 
std::equal
 - 然后将无法编译,因为这些类型都不是迭代器。


最简单的解决方案是不传递显式的

std::initializer_list<int>

 而只是手动传递 
std::vector<int>

或者,您可以添加额外的

n::equal

 重载来处理这种情况:

bool equal(S a, S b, std::vector<int> = {1,2}); bool equal(S a, S b, std::initializer_list<int> xs) { return equal(a, b, std::vector<int>(xs)); }
    
© www.soinside.com 2019 - 2024. All rights reserved.