Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I force C++ to choose a function from the global namespace?

Tags:

c++

templates

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?

like image 580
kamikaze Avatar asked Oct 11 '25 21:10

kamikaze


1 Answers

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 #included). The former will use ADL to find the best matching pow() function, which may be std::pow.

like image 110
NathanOliver Avatar answered Oct 14 '25 09:10

NathanOliver