简体   繁体   English

模板编程:对重载函数的歧义调用

[英]template programming: ambiguous call to overloaded function

I am implementing a sorting algorithm as personal training (no homework!). 我正在将排序算法作为个人培训来实现(无需做作业!)。 I have the following code (excluding imports etc.): 我有以下代码(不包括导入等):

        template<class RandomIt, class Compare>
        void sort(RandomIt first, RandomIt last, Compare comp)
        {
            /* actual sorting code is here */
        }

        template<class RandomIt>
        void sort(RandomIt first, RandomIt last)
        {
            std::function<bool(decltype(*first), decltype(*last))> comp = [](decltype(*first) a, decltype(*last) b)
            {
                return a < b;
            };

            sort (first, last, comp);
        }

Trying to call this code with a test array 尝试通过测试数组调用此代码

    auto test_array_1 = std::make_unique <std::array < uint64_t,SORTING_TEST_LENGTH >> ();
    std::copy(std::cbegin(*template_array), std::cend(*template_array), std::begin(*test_array_1));

    sort(std::begin(*test_array_1), std::end(*test_array_1));

The compiler complains about "ambiguous call to overloaded function" (VC++ C2668). 编译器抱怨“对重载函数的歧义调用”(VC ++ C2668)。 From my understanding the call should not be ambiguous though. 从我的理解来看,这个电话应该不会模棱两可。 Also giving the call in the second sort function the template parameters for the first sort function does not have any effect. 同样,给第二个排序函数中的调用一个第一个排序函数的模板参数没有任何作用。

What am I missing here? 我在这里想念什么? Why does the compiler consider the second call "ambiguous"? 为何编译器将第二个调用视为“模棱两可”?

The problem is two fold. 问题有两个。

First, sort is found via ADL, so you get two overloads, and they both match. 首先,通过ADL查找sort ,因此您将获得两个重载,并且它们都匹配。 In general, naming functions the same as std functions when you are not trying to ADL-overload is fraught, due to the possibility of ADL-induced ambiguity. 通常,由于ADL可能引起歧义,因此当您不尝试ADL重载时,命名功能与std函数相同。

Now, this only happens when passing types from namespace std; 现在,仅当从namespace std;传递类型时才会发生这种情况namespace std; Sometimes iterators are from this namespace, but not in this case : array uses raw pointer iterators. 有时迭代器来自此名称空间,但在这种情况下不是: array使用原始指针迭代器。 The trigger for ADL finding std::sort is the std::function . ADL查找std::sort的触发器是std::function

Which brings me to the next problem: there is very little to be gained, and much to be lost, by std::function in the above code. 这就引出了下一个问题:上面代码中的std::function带来的收获很少,而损失的很多。 Replace it with auto . 将其替换为auto Pass low level sorting algorithms an inlineable comparison object. 将低级排序算法传递给可内联的比较对象。

You still do not want to call it sort . 您仍然不希望将其称为sort If you call it sort you need to qualify calls with the namespace, or (sort) to block ADL. 如果调用它进行sort ,则需要使用名称空间来限定调用,或(sort)以阻止ADL。

The ADL rule is that both the "usual" functions, and functions in the namespace of arguments, and namespace of what arguments point to, and template arguments of arguments, etc, are considered for overload resolution. ADL规则是考虑“重载”函数,以及参数名称空间中的功能,参数指向的名称空间,参数指向的名称空间以及参数的模板参数等。 This is Argument Dependent Lookup, or ADL, or Koenig lookup. 这是基于参数的查找或ADL或Koenig查找。 It means that namespace pollution of a kind can occur when using types from another namespace (which is sad), but it also makes some nice magic happen (like std::cout << "hello world\\n";`) 这意味着当使用另一个命名空间中的类型时,可能会发生某种类型的命名空间污染(这很可悲),但是这也会使一些不错的事情发生(例如std :: cout <<“ hello world \\ n”;`)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM