我遇到问题gcc 4.9.2
(-std = c ++ 11)没有编译一段代码,错误信息是
调用重载'InsertDataIntoInputMap(int&,boost :: shared_ptr&)'是不明确的
代码使用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参数的函数?
答案 0 :(得分:3)
这个问题可以简化为部分排序的不精确性:仍然会考虑和比较没有出现与演绎有关的模板参数的对。该问题也由CWG #455和#885解决。
在您的示例中,重载解析无法区分重载。因此,部分排序是必要的。部分排序将尝试执行两次推导,参数类型P
为typename C::InputDataMap::key_type
但是,这种推论注定要失败,因为C
仅出现在非推断的上下文中。即两个模板(对于该特定对)的类型至少与相应的其他模板中的类型一样专用 - 反过来,这意味着两个模板都不比另一个模板更专业。
正如@ T.C.所述,CWG #1391的解决方案有所帮助。这部分特别是:
将14.8.2.4 [temp.deduct.partial]第4段改为:
上面从参数模板中提名的每种类型和参数模板中的相应类型都用作
P
和A
的类型。 如果特定P
不包含参与模板参数扣除的模板参数,则P
不会用于确定排序。
现在,第一个参数对在两种方式中都被完全忽略(因为C
的类型仅由显式参数列表确定),并且发现第二个重载更加专业化。
答案 1 :(得分:1)
一个简单的别名可以使代码工作:
#include <iostream>
#include <map>
#include <boost/shared_ptr.hpp>
struct Proxy
{
typedef std::map<int, int> InputDataMap;
int a;
};
template<class C, class D, class F = typename C::InputDataMap::key_type>
void InsertDataIntoInputMap(
const F& key,
const D val)
{
std::cout << "Not shared\n";
}
template<class C, class D, class F = typename C::InputDataMap::key_type>
void InsertDataIntoInputMap(
const F& 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);
}
但是imo。这应该不起作用,因为我认为,草案说,编译器不会考虑C :: InputDataMap -
中的命名空间class F = typename C::InputDataMap::key_type
和F将是一个非推断的上下文(如key_type)。