免责声明:这或多或少是出于教育目的,因此应该忽略有关所示包装的意义的讨论。
在自己的命名空间中考虑以下模板:
// 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)。
答案 0 :(得分:2)
由于Argument Dependent-name Lookup(ADL),调用不明确。由于您的参数是std::string
,因此会考虑名称空间make_pair()
中的std
。
这就是为什么,例如当你调用std::cout << 21
时,你不需要为std
指定命名空间operator<<
:因为ADL它是由编译器计算的。
如果要强制使用自己的实现,则需要在调用前添加名称空间fc::make_pair(...)
。