Reputation: 311
Disclaimer: This is more or less for educational purposes, so a discussion about the meaningfulness of the shown wrapping should be neglected.
Consider the following template in its own namespace:
// 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));
}
}
When I try to use it from within this namespace:
// 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);
}
}
I get the following compiler error:
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
]
As soon as I rename my wrapper to something else, e.g. make_my_pair
, everything works.
It also seems to be related to the const reference parameter of fc::my_function
which I use for the first value of the pair. When I change the call to my wrapper to just use (primitive) rvalues, e.g. auto my_pair = fc::make_pair(1.42, 42);
, everything works. It also works, when I directly use std::make_pair
.
Why does the compiler take the implementation of the std namespace into account in the first place? I did not explicitly use std::make_pair
(with the exception of the wrapper definition) nor did I do using namespace std
at any time. I am using Visual Studio 2015 (VC14).
Upvotes: 0
Views: 346
Reputation: 5336
The call is ambiguous because of Argument Dependent-name Lookup (ADL). Because your argument is a std::string
, then the make_pair()
in namespace std
is considered.
This is why, for example when you call std::cout << 21
, you do not need to specify the namespace std
for operator<<
: because of ADL it is figured by the compiler.
If you want to enforce that your own implementation is used, then you need to prefix the call with the namespace fc::make_pair(...)
.
Upvotes: 2