我遇到了一个问题,gcc 4.9.2
(使用 -std=c++11)没有编译一段代码,错误消息为
call of overloaded 'InsertDataIntoInputMap(int&, boost::shared_ptr&)' is ambiguous
代码确实使用 msvc 2013 编译
#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 进行编译:
#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 参数的函数?
最佳答案
这个问题可以简化为偏序中的不精确性:仍然考虑和比较那些没有出现模板参数的对。 CWG #455 已解决该问题。和 #885也是。
在您的示例中,重载解析无法区分重载。因此,部分排序是必要的。并且偏序会尝试进行两次推导,参数类型P
为typename C::InputDataMap::key_type
。
然而,这种演绎注定要失败,因为 C
只出现在非演绎的上下文中。 IE。两个模板中的类型(对于该特定对)至少不像其他模板中的类型那样专门化——这反过来意味着没有一个模板比另一个模板更专门化。
正如@T.C. 所指出的,CWG #1391 的分辨率有帮助。特别是这部分:
Change 14.8.2.4 [temp.deduct.partial] paragraph 4 as follows:
Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of
P
andA
. If a particularP
contains no template-parameters that participate in template argument deduction, thatP
is not used to determine the ordering.
现在,第一个参数对在两种方式中都被完全忽略(因为 C
的类型完全由显式参数列表确定),而第二个重载被发现更加专业。
关于c++ - GCC 4.9 模棱两可的重载模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31563235/