c++ - GCC 4.9 模棱两可的重载模板特化

标签 c++ c++11 gcc

我遇到了一个问题,gcc 4.9.2(使用 -std=c++11)没有编译一段代码,错误消息为

call of overloaded 'InsertDataIntoInputMap(int&, boost::shared_ptr&)' is ambiguous

代码确实使用 msvc 2013 编译

#include <iostream>
#include <map>
#include <boost/shared_ptr.hpp>

struct Proxy
{
    typedef std::map<int, int> InputDataMap;    
    int a;
};

template<class C, class D>
void InsertDataIntoInputMap(
    const typename C::InputDataMap::key_type& key,
    const D val)
{
    std::cout << "Not shared\n";
}

template<class C, class D>
void InsertDataIntoInputMap(
    const typename C::InputDataMap::key_type& key,
    const boost::shared_ptr<D> val)
{
    if (val)
    {
        std::cout << "Shared\n";
    }
}

int main() {
    int a;
    boost::shared_ptr<double> x(new double(4.5));

    InsertDataIntoInputMap<Proxy>(a, x);
}

虽然以下内容确实可以同时使用 gcc 和 msvc 进行编译:

#include <iostream>
#include <boost/shared_ptr.hpp>

template<class C, class D>
void InsertDataIntoInputMap(
    const C& key,
    const D val)
{
    std::cout << "Not shared\n";
}

template<class C, class D>
void InsertDataIntoInputMap(
    const C& key,
    const boost::shared_ptr<D> val)
{
    if (val)
    {
        std::cout << "Shared\n";
    }
}

int main() {
    int a = 0;
    boost::shared_ptr<double> x(new double(4.5));

    InsertDataIntoInputMap<int>(a, x);

    return 0;
}

我会认为编译器在这两种情况下都应该使用带有 boost::shared_ptr 参数的函数?

最佳答案

这个问题可以简化为偏序中的不精确性:仍然考虑和比较那些没有出现模板参数的对。 CWG #455 已解决该问题。和 #885也是。

在您的示例中,重载解析无法区分重载。因此,部分排序是必要的。并且偏序会尝试进行两次推导,参数类型Ptypename C::InputDataMap::key_type
然而,这种演绎注定要失败,因为 C 只出现在非演绎的上下文中。 IE。两个模板中的类型(对于该特定对)至少不像其他模板中的类型那样专门化——这反过来意味着没有一个模板比另一个模板更专门化。

正如@T.C. 所指出的,CWG #1391 的分辨率有帮助。特别是这部分:

Change 14.8.2.4 [temp.deduct.partial] paragraph 4 as follows:

Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A. If a particular P contains no template-parameters that participate in template argument deduction, that P is not used to determine the ordering.

现在,第一个参数对在两种方式中都被完全忽略(因为 C 的类型完全由显式参数列表确定),而第二个重载被发现更加专业。

关于c++ - GCC 4.9 模棱两可的重载模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31563235/

相关文章:

c++ - 为什么当我在字符变量中键入多个字符时它会起作用?

c++ - 使用许多静态成员有问题吗?

c++ - 用字节序列初始化数组的有效方法?

c - 段错误(核心转储)-我的代码出了什么问题

gcc - 如何声明 __sync_fetch_and_add?

c++ - 在 `std::map` 中存储对象时代码崩溃

c++ - Doxygen 基类有时无法解析

c++ - move 由逗号运算符抑制的构造函数

c++ - 是否可以将一组值传递给可变参数模板声明,类似于斐波那契数列的求解方式

c - 为什么GCC会生成 "mov 0x8,%edx"指令导致崩溃?