【问题标题】:Ambiguous template binary operators?模棱两可的模板二元运算符?
【发布时间】:2015-12-18 09:43:01
【问题描述】:

考虑下面的代码

namespace std {
    struct type1 {/* Definition */};
    template <class T> constexpr T operator+(const type1& x1, const T& x);
    template <class T> constexpr T operator+(const T& x, const type1& x1);
}

namespace other {
    struct type2 {/* Definition */};
    template <class T> constexpr T operator+(const type2& x2, const T& x);
    template <class T> constexpr T operator+(const T& x, const type2& x2);
}

int main(int argc, char** argv) 
{
    std::type1 var1;
    other::type2 var2;
    auto x = var1 + var2; // What will happen here?
}
  • auto x = var1 + var2 行会发生什么?

  • 这是一种已定义的行为吗?

  • 这是否意味着标准库永远不会定义泛型运算符,只在一侧使用模板以避免冲突使用?

【问题讨论】:

  • 至于“会发生什么”不如先试试看告诉我们吧?
  • @101010 他们不再是了
  • 这纯粹是学术性的(不是说这有什么问题),还是你有一个用例?
  • @xophos 我想到的问题如下:标准委员会是否可以标准化二进制运算符重载,其中一侧是 std:: 类,另一侧是不受约束的模板类型?
  • @xophos 如果没有约束,我看不出如何提供有意义的实现。

标签: c++ c++11 operator-overloading std ambiguous


【解决方案1】:

根据定义明确的depended name look up(又名 Koenig Lookup)规则。除了通常的非限定名称查找所考虑的范围和命名空间之外,编译器还将在 operator+ 参数的命名空间中查找函数名称。

因此,编译器会将匹配的重载运算符(即来自命名空间stdother)添加到重载集。

因此,您会收到一个模棱两可的调用错误。

【讨论】:

    【解决方案2】:

    您应该在符合标准的编译器上得到一个模棱两可的运算符错误。 您的程序格式不正确,因为两个版本的重载都符合候选条件。

    【讨论】:

      【解决方案3】:

      此代码会导致未定义的行为。不允许将您自己的东西添加到 namespace std;,除了对现有模板的显式特化。

      【讨论】:

      • 这是一个正确但无用的答案,完全无法解决OP的意思。不过,这可能作为评论很有用。
      • @hvd 也许你可以通过编辑问题来启发我们,以反映你认为 OP 的意思
      • 这个问题已经很有意义了。假装OP使用STD而不是std;问题不在于用户代码向std 命名空间添加类型。
      • @hvd 在这种情况下,第三个项目符号的答案是“标准库永远不会在命名空间STD 中定义运算符”......这(也是?)似乎正确但没用
      • 问题在要点 1 和 2 中询问如果不同命名空间中的多个类型具有为它们定义的模板运算符,会发生什么情况。 (不同的命名空间可能相关,也可能不相关。)问题在要点 3 中询问标准是否会因此而具有 / 具有模板运算符。当然,用户代码不会使用std 命名空间,标准库代码会。
      猜你喜欢
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 1970-01-01
      相关资源
      最近更新 更多