模板编程:对重载函数的不明确调用 [英] template programming: ambiguous call to overloaded function

查看:37
本文介绍了模板编程:对重载函数的不明确调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实施一个排序算法作为个人训练(没有家庭作业!).我有以下代码(不包括进口等):

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));

编译器抱怨对重载函数的调用不明确"(VC++ C2668).根据我的理解,这个电话不应该是模棱两可的.同样在第二个排序函数中调用第一个排序函数的模板参数也没有任何影响.

The compiler complains about "ambiguous call to overloaded function" (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"?

推荐答案

问题是两方面的.

首先,sort 是通过 ADL 找到的,因此您会得到两个重载,并且它们都匹配.一般来说,当您不尝试 ADL 过载时,命名与 std 函数相同的函数是令人担忧的,因为 ADL 可能会引起歧义.

First, sort is found via ADL, so you get two overloads, and they both match. 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.

现在,这只发生在从 namespace std; 传递类型时,有时迭代器来自这个命名空间,但在这种情况下不是:array 使用原始指针迭代器.ADL 查找 std::sort 的触发器是 std::function.

Now, this only happens when passing types from namespace std; Sometimes iterators are from this namespace, but not in this case : array uses raw pointer iterators. The trigger for ADL finding std::sort is the std::function.

这让我想到了下一个问题:通过上述代码中的 std::function 获得的收益很少,但损失很多.将其替换为 auto.将低级排序算法传递给内联比较对象.

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. Replace it with auto. Pass low level sorting algorithms an inlineable comparison object.

您仍然不想将其称为sort.如果你调用它 sort 你需要用命名空间限定调用,或者 (sort) 来阻止 ADL.

You still do not want to call it sort. If you call it sort you need to qualify calls with the namespace, or (sort) to block ADL.

ADL 规则是通常的"函数、参数命名空间中的函数、参数指向的命名空间以及参数的模板参数等都被考虑用于重载解析.这是参数依赖查找,或 ADL,或 Koenig 查找.这意味着在使用来自另一个名称空间的类型时可能会发生某种名称空间污染(这很可悲),但它也会发生一些不错的魔术(例如 std::cout << "hello world\n";`)

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. This is Argument Dependent Lookup, or ADL, or Koenig lookup. 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";`)

这篇关于模板编程:对重载函数的不明确调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆