I have a container and want to rely on whoever uses my library to make sure that a function is available for the underlying value_type (pow() in the coming example). And I want the compiler to use that function inside of a member function with the same name, based on its signature.
My attempt to create a minimal example:
#include <iostream>
#include <cmath>
using std::pow;
template <typename T>
struct container {
T value;
container<T> pow(T const exp) const {
return {pow(this->value, exp)};
}
};
int main() {
container<double> value{81.};
std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n';
return 0;
}
The container<> offers a pow() method, that is supposed to rely on pow() being available from the underlying type in the global namespace.
This is supposed to facilitate the use of custom number-like types. I.e. library users should be able to define their own types that act like numbers and supply a pow() function for their type, to make it container<> compatible.
The problem, neither clang nor gcc pick up the function from the global namespace:
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<double>::pow' requested here
std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n';
^
pow.cpp:10:2: note: 'pow' declared here
container<T> pow(T const exp) const {
^
If I use the global namespace explicitly, it works as expected:
container<T> pow(T const exp) const {
return {::pow(this->value, exp)};
}
And the program produces the expected output:
c++ -std=c++11 pow.cpp -o pow
./pow
81^0.25 = 3
That solves the actual problem, but I wonder why it is necessary? Shouldn't the signature match allow the compiler to select the right function?
You need to introduce the std::pow
function in your pow
function. This allows the compiler to fall back to std::pow
if ADL fails
#include <iostream>
#include <cmath>
template <typename T>
struct container {
T value;
container<T> pow(T const exp) const {
using std::pow;
return {pow(this->value, exp)};
}
};
int main() {
container<double> value{81.};
std::cout << value.value << "^0.25 = " << value.pow(.25).value << '\n';
return 0;
}
Live Example
This is the same thing you would do when building a custom swap function. You can see it working with a class that has its own pow
here
edit for those who don't understand lookup. It's important to understand the difference between
T func(T a, T b)
{
using std::pow;
return pow(a,b);
}
and
T func(T a, T b)
{
return std::pow(a,b);
}
The latter always calls std::pow()
and will fail if T
cannot be converted to double
(or std::complex<double>
if <complex>
was #include
d). The former will use ADL to find the best matching pow()
function, which may be std::pow
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With