【问题标题】:Workaround clang warning -Wambiguous-member-template解决方法 clang 警告 -Wambiguous-member-template
【发布时间】:2013-12-02 11:07:09
【问题描述】:

如何解决此 clang 警告?这在包含 STL <set> 并且另外具有模板化 set() 函数的代码中经常出现。

我不想全局禁用警告,但也不想手动为每个包含 <set> 的文件(太多)。

template<typename T> struct set{};
template<typename T> struct trait { typedef const T& type; };
struct Value {
  template<typename T> void set(typename trait<T>::type value) {}
};
void foo() {
  Value v;
  v.set<double>(3.2);
}
clang.cpp:8:9:警告:在成员访问表达式中查找“set”不明确;使用“值”的成员 [-Wambiguous-member-template] v.set(3.2); ^ clang.cpp:4:29:注意:在对象类型“值”中的查找指的是这里 模板无效集(类型名称特征::类型值){} ^ clang.cpp:1:29: 注意:从当前范围查找指的是这里 模板结构集{}; ^ 生成 1 个警告。

显而易见的解决方案是不使用模板化的 set() 方法,但这似乎相当有限。

【问题讨论】:

  • 如何正确使用命名空间并避免使用命名空间标准?
  • 你用的是哪个版本的clang?
  • @DyP:来自 SVN 的 release_34
  • @MartinRichtarsky 我认为整个问题已经在DR 1111 中得到解决,它具有 FDIS 状态 - AFAIK 现在是标准的一部分。因此,您应该将警告解释为C++03 中的格式错误,现在允许且明确。了解这一点,您可能希望按照 n.m. 的建议禁用警告

标签: c++ templates clang


【解决方案1】:

警告似乎无效。在这种情况下,标准 [basic.lookup.classref] 似乎并没有表明存在歧义或需要任何诊断。以下是相关段落:

  1. 在类成员访问表达式 (5.2.5) 中,如果 .-&gt; 令牌后紧跟一个标识符,后跟一个 &lt;,则必须查找标识符以确定 @987654325 @ 是模板的开头 参数列表 (14.2) 或小于运算符。标识符首先在对象的类中查找 表达。如果找不到标识符,则在整个后缀表达式的上下文中查找它 并应命名一个类模板。

我会全局禁用警告。

【讨论】:

  • n3242 和 n3337 之间似乎发生了变化,标准已在这两者之间发布。在这种情况下,n3242 需要一个错误,但更新的版本不需要。 n3242 [basic.lookup.classref]/1,bullet 3:“如果找到的名称是类模板,则它应引用与在对象表达式的类中找到的实体相同的实体,否则程序是非良构的。”
  • @dyp 这是一个 C++03 规则,已在 C++1 see my answer here for more details 中修复,是的,它很古怪。
【解决方案2】:

你是对的,显而易见的解决方案是不要定义 conflicting 模板set 方法和类。你范围内的名称查找规则在类和方法之间不能有歧义,即符号set不能同时引用两者,你​​必须使用命名空间来消除歧义。

您可能没有在命名空间std 中定义set 方法,所以我只能假设您在您的作用域中注入了std::set,使用using std::setusing namespace std

一般情况下,using namepsace std 是个坏主意,因为您无法控制它在您的作用域中注入的符号(取决于递归包含),并且您并不总是控制这可能与哪些其他符号发生冲突。

在您的情况下,正如 Dieter 所说,最简单的解决方案是通过删除相关的 using 子句来阻止 set 引用 std::set。然后您必须使用std::set 来命名它,而不仅仅是set,但不会再有任何冲突。

【讨论】:

  • 有道理。代码库犯了太多usings,但清理它们需要一段时间。
猜你喜欢
  • 1970-01-01
  • 2011-08-13
  • 2020-08-05
  • 1970-01-01
  • 2013-04-29
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 2018-11-26
相关资源
最近更新 更多