Cpp 操作符重载函数在模板里找不到的问题记录
目录
注意
本文最后更新于 2023-11-13,文中内容可能已过时。
主要内容
笔者此前在使用 dbg-macro 库的时候碰到了一个奇怪的问题, 就是操作符的重载函数无法被找到。
准确的说是被模板的 SFINAE 原则忽略了。
大致的情况是这样的:
-
有一个结构体叫做
ImVec2
,它处于全局命名空间里面。 来自库imgui -
操作符的重载函数放在一个叫做
sight
的命名空间里面。 -
1 2 3 4 5 6 7
namespace sight { void test(){ ImVec2 v; std::cout << v; // ok dbg(v); // fail } }
-
大致代码如上面所述。
-
解决办法是把 操作符重载函数和类型放入同一个命名空间, 比如把操作符的重载函数移到全局命名空间里面。
-
在类型和操作符重载函数在不同的命名空间的时候, ADL 规则是无法生效的。 这里的问题是,似乎模板函数在生成的时候没有搜寻当前的命名空间, 但是正常函数调用的时候却会搜寻。
-
可能是一个编译器 bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83035. 不过笔者使用的是 clang, 也是存在这个问题的。
dbg(v) 的解释
dbg-macro
是一个用于方便输出调试信息的库, 特性大致如下
- Easy to read, colorized output (colors auto-disable when the output is not an interactive terminal)
- Prints file name, line number, function name and the original expression
- Adds type information for the printed-out value
- Specialized pretty-printers for containers, pointers, string literals, enums,
std::optional
, etc.- Can be used inside expressions (passing through the original value)
- The
dbg.h
header issues a compiler warning when included (so you don’t forget to remove it).- Compatible and tested with C++11, C++14 and C++17.
dbg
是一个宏, 最终拓展开的时候,会调用下面的函数。
|
|
完成代码可以在这里浏览: https://github.com/sharkdp/dbg-macro/blob/master/dbg.h