解决方法clang warning -Wambiguous-member-template

时间:2013-12-02 11:07:10

标签: c++ templates clang

如何解决此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: warning: lookup of 'set' in member access expression is ambiguous; using member of 'Value' [-Wambiguous-member-template]
      v.set(3.2);
        ^
clang.cpp:4:29: note: lookup in the object type 'Value' refers here
  template void set(typename trait::type value) {}
                ^
clang.cpp:1:29: note: lookup from the current scope refers here
template struct set{};
                ^
1 warning generated.

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

2 个答案:

答案 0 :(得分:3)

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

  1. 在类成员访问表达式(5.2.5)中,如果.->标记后面紧跟着标识符后跟<,则必须查找标识符确定<是否是模板的开头 参数列表(14.2)或小于运算符。首先在对象的类中查找标识符 表达。如果未找到标识符,则在整个postfix-expression的上下文中查找它 并且应命名一个类模板。
  2. 我会全局禁用警告。

答案 1 :(得分:2)

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

您可能没有在命名空间set中定义std方法,所以我只能假设您在范围内注入了std::setusing std::set或{{1 }}

通常,using namespace std如果是个坏主意,因为你不控制它在你的范围内注入的符号(取决于递归包含),并且你并不总是控制这可能与之冲突的其他符号。

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