首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >GCC 4.9歧义重载模板专门化

GCC 4.9歧义重载模板专门化
EN

Stack Overflow用户
提问于 2015-07-22 20:30:28
回答 2查看 970关注 0票数 16

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

重载的‘InsertDataIntoInputMap(

&,boost::shared_ptr&)’的int调用不明确

代码可以使用msvc 2013进行编译

代码语言:javascript
复制
#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编译的:

代码语言:javascript
复制
#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参数的函数?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-08 05:05:06

这个问题可以归结为偏序中的不精确:在推导中没有出现模板参数的对仍然被考虑和比较。CWG #455#885也解决了这个问题。

在您的示例中,重载解析无法区分重载。因此,偏序是必要的。偏序将尝试执行两次演绎,参数类型Ptypename C::InputDataMap::key_type

然而,这种推论注定要失败,因为C只出现在非演绎的上下文中。即,来自两个模板的类型(对于该特定对)至少不像来自各自的另一个模板的类型那样专门化-这反过来意味着这两个模板中没有一个比另一个更专门化。

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

更改14.8.2.4 temp.deduct.partial第4段如下:

上面从参数模板中指定的每个类型和参数模板中的相应类型都用作PA的类型。如果特定的模板P 不包含参与模板实参推导的模板参数,则不使用该模板参数来确定排序。

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

票数 3
EN

Stack Overflow用户

发布于 2015-08-06 21:21:52

一个简单的别名就可以让代码正常工作:

代码语言:javascript
复制
#include <iostream>
#include <map>
#include <boost/shared_ptr.hpp>

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

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

template<class C, class D, class F = typename C::InputDataMap::key_type>
void InsertDataIntoInputMap(
    const F& 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);
}

但是国际海事组织。这应该行不通,因为我认为,草案说,编译器不会考虑C::InputDataMap - Namespace在

代码语言:javascript
复制
class F = typename C::InputDataMap::key_type

而F将是一个非推导的上下文(如key_type)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31563235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档