【问题标题】:Function overloading with initialization_list causing ambiguity带有initialization_list的函数重载导致歧义
【发布时间】:2015-05-26 23:03:50
【问题描述】:

我正在尝试使用initialization_list 重载函数作为具有变化的参数以接受映射和向量以及整数。编译器抱怨函数解析不明确。我想知道是什么导致了歧义以及如何解决它

#include <memory>
#include <iostream>
#include <map>
#include <initializer_list>

std::shared_ptr<int> foo(const std::initializer_list<std::pair<const std::string, std::shared_ptr<int> > >& il)
{
    return std::make_shared<int>();
}
std::shared_ptr<int> foo(const std::initializer_list<std::shared_ptr<int> > & il)
{
    return std::make_shared<int>();
}

std::shared_ptr<int> foo(int num)
{
    return std::make_shared<int>();
}

int main()
{
    foo({ { "a", foo(10) } });
}

Try It OUT >>>

注意

  1. 我用 VS2013 和 g++ 都试过了,都出错了。
  2. 根据@chris,上面的代码编译在clang
  3. 标准是怎么说的?还是它实际上说明了什么?

【问题讨论】:

  • @chris libstdc++ 似乎只给出了错误。
  • 该标准确实有前提条件:要求:p 应可转换为 T*。不过,我不知道它需要实现对前置条件做什么。我敢打赌 libstdc++(可能不使用 SFINAE)和 libc++(确实使用)都是正确的。
  • @chris:如果编译器不需要实现前置条件,那么它可能会令人困惑。我的猜测是,指针是不可转换的,所以不应该是一个模棱两可的调用。
  • @chris 违反 requires 部分会产生 UB。 SFINAE 在 remarks 子句中被强制执行。

标签: c++ c++11 shared-ptr language-lawyer overloading


【解决方案1】:

产生歧义的原因

shared_ptr 有一个带有两个参数的构造函数:

template<class Y, class D> shared_ptr(Y* p, D d);

与初始化列表{ "a", foo(10) } 以及pair 匹配。 (或者,如果不是那么好,那么足够接近一些编译器会出错。确切的规则让我大吃一惊,所以我不会试图弄清楚哪个编译器在技术上是正确的。)

如何解决

假设您想要第一个重载,请提供 pair 类型,而不是更通用的初始化列表:

foo({ std::make_pair( "a", foo(10) ) });

标准是怎么说的?还是它实际上说明了什么?

它说了很多,通常用相当不透明的语言。我无法引用 [over.match] 的 20 页内容,也没有语言律师技能来总结它们在此处的应用,同时保持我的理智。

【讨论】:

  • 如果指针不可转换,libc++ 似乎将这个重载从集合中移除:template&lt;class _Yp, class _Dp&gt; shared_ptr(_Yp* __p, _Dp __d, typename enable_if&lt;is_convertible&lt;_Yp*, element_type*&gt;::value, __nat&gt;::type = __nat());
  • 它是 shared_ptr 的无效构造函数,但这并不意味着应该调用另一个重载,这取决于您如何实现“表达式 d(p) 应格式正确”以及如何与您的重载解决规则交互。可能是Y* 的更紧密匹配可能会覆盖无法满足第二个参数的约束(因为它与模板匹配)。
  • 正如@chris 所引用的那样,有一个前提条件是指针需要可转换,在这种情况下不是,我想知道它是否足够接近或前提条件已被无意中省略。在后一种情况下,我们可以提出错误报告。 [请注意,您的回答并未解释指针可转换性,因此无法接受,但如果您增加更多清晰度,则会这样做]
  • @abhijit:对不起,这就是我所能提供的全部内容。我已经解释了为什么编译器可能会发现它不明确,以及如何使它完全明确。你需要一个更高级别的语言律师来判断哪些实现是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多