为什么我在单独的命名空间中转发到 std::make_pair 模棱两可

Why is my forward to std::make_pair in a separate namespace ambiguous?

本文关键字:std make 模棱两可 pair 转发 单独 命名空间 为什么      更新时间:2023-10-16

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

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

// 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 引用参数有关。当我将对包装器的调用更改为仅使用(原始(右值时,例如 auto my_pair = fc::make_pair(1.42, 42);,一切正常。当我直接使用std::make_pair时,它也可以工作.

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

由于参数相关名称查找 (ADL( 的原因,调用不明确。因为您的参数是std::string,所以会考虑命名空间std中的make_pair()

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

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