为什么我在单独的命名空间中向std :: make_pair转发模糊不清?

时间:2017-05-23 08:02:57

标签: c++ visual-c++ c++14

免责声明:这或多或少是出于教育目的,因此应该忽略有关所示包装的意义的讨论。

在自己的命名空间中考虑以下模板:

// file my_make_pair.h

#pragma once
#include <utility>

namespace fc {

    template<typename T, typename U>
    decltype(auto) make_pair(T&& first, U&& second)
    {
        return std::make_pair(std::forward<T>(first),
                              std::forward<U>(second));
    }

}

当我尝试在此命名空间中使用它时:

// file my_test.cpp

#include "my_make_pair.h"
#include <string>

namespace fc {

    void my_function(const std::string& name) {
        auto my_pair = make_pair(name, 42);
    }

}

我收到以下编译错误:

could be 'decltype(auto) fc::make_pair<const std::string&,int>(T,U &&)'
    with
    [
        T=const std::string &,
        U=int
    ]

or 'std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,int> std::make_pair<const std::string&,int>(_Ty1,_Ty2 &&)'
                     [found using argument-dependent lookup]
    with
    [
        _Ty1=const std::string &,
        _Ty2=int
    ]

我将包装器重命名为其他内容,例如make_my_pair,一切正常。

它似乎也与我用作该对的第一个值的fc::my_function的const引用参数有关。当我将对包装器的调用更改为仅使用(原始)rvalues时,例如auto my_pair = fc::make_pair(1.42, 42);,一切正常。当我直接使用std::make_pair时,它也有效。

为什么编译器首先会考虑std命名空间的实现?我没有明确使用std::make_pair(包装器定义除外),也没有随时使用using namespace std。我使用的是Visual Studio 2015(VC14)。

1 个答案:

答案 0 :(得分:2)

由于Argument Dependent-name Lookup(ADL),调用不明确。由于您的参数是std::string,因此会考虑名称空间make_pair()中的std

这就是为什么,例如当你调用std::cout << 21时,你不需要为std指定命名空间operator<<:因为ADL它是由编译器计算的。

如果要强制使用自己的实现,则需要在调用前添加名称空间fc::make_pair(...)