我有一个容器,并希望依赖于使用我的库的人来确保函数可用于基础value_type(即将到来的示例中的pow()).我希望编译器根据其签名在具有相同名称的成员函数内使用该函数.
我试图创建一个最小的例子:
#include#include using std::pow; template struct container { T value; container pow(T const exp) const { return {pow(this->value, exp)}; } }; int main() { container value{81.}; std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n'; return 0; }
所述容器<>提供POW()方法,是应该依靠POW()是可从在全局命名空间的基础类型.
这应该有助于使用自定义数字类型.即图书馆用户应该能够定义他们自己的类型,类似于数字,并为其类型提供pow()函数,使其容器<>兼容.
问题,clang和gcc都没有从全局命名空间中获取函数:
c++ -std=c++11 pow.cpp -o pow pow.cpp:11:28: error: too many arguments to function call, expected single argument 'exp', have 2 arguments return {pow(this->value, exp)}; ~~~ ^~~ pow.cpp:17:50: note: in instantiation of member function 'container::pow' requested here std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n'; ^ pow.cpp:10:2: note: 'pow' declared here container pow(T const exp) const { ^
如果我显式使用全局命名空间,它按预期工作:
containerpow(T const exp) const { return {::pow(this->value, exp)}; }
该程序产生预期的输出:
c++ -std=c++11 pow.cpp -o pow ./pow 81^0.25 = 3
这解决了实际问题,但我想知道为什么有必要?签名匹配不应该允许编译器选择正确的函数吗?
您需要在std::pow
函数中引入该pow
函数.这允许编译器std::pow
在ADL失败时回退
#include#include template struct container { T value; container pow(T const exp) const { using std::pow; return {pow(this->value, exp)}; } }; int main() { container value{81.}; std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n'; return 0; }
Live Example
这与构建自定义交换功能时的操作相同.你可以看到它有它自己的一类工作pow
在这里
编辑那些不了解查找的人.了解它们之间的区别非常重要
T func(T a, T b) { using std::pow; return pow(a,b); }
和
T func(T a, T b) { return std::pow(a,b); }
std::pow()
如果T
不能转换为double
(或者std::complex
如果
是#include
d),后者总是调用并将失败.前者将使用ADL找到最佳匹配pow()
函数,这可能是std::pow
.