如何解决此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()
方法,但这似乎相当有限。
答案 0 :(得分:3)
警告似乎无效。在这种情况下,标准[basic.lookup.classref]似乎并不表示存在歧义,或者需要任何诊断。以下是相关段落:
.
或->
标记后面紧跟着标识符后跟<
,则必须查找标识符确定<
是否是模板的开头
参数列表(14.2)或小于运算符。首先在对象的类中查找标识符
表达。如果未找到标识符,则在整个postfix-expression的上下文中查找它
并且应命名一个类模板。我会全局禁用警告。
答案 1 :(得分:2)
你是对的,显而易见的解决方案不是定义冲突的模板set
方法和类。范围中的名称查找规则在类和方法之间不得含糊不清,即符号set
不能同时引用两者,您必须使用命名空间来消除歧义。
您可能没有在命名空间set
中定义std
方法,所以我只能假设您在范围内注入了std::set
,using std::set
或{{1 }}
通常,using namespace std
如果是个坏主意,因为你不控制它在你的范围内注入的符号(取决于递归包含),并且你并不总是控制这可能与之冲突的其他符号。
在您的情况下,正如Dieter所说,最简单的解决方案是通过删除相关的using namepsace std
条款来阻止set
引用std::set
。然后,您必须使用using
来命名,而不仅仅是std::set
,但不会再发生任何冲突。