ADL in constructor initialization list

432 Views Asked by At

How can I enable ADL in a constructor initialization list? For example, let's say that I have a bignum that has a namespace-level abs function. Now I want to write a class Foo that initializes its members with the absolute values of the instances passed to the constructor; it should the use namespace-level abs if it exists and std::abs otherwise:

template<typename T>
struct Foo
{
    T _data;

    Foo(T data):
        _data(abs(data)) // I want find abs with ADL here
    {}
};

Using declarations are forbidden at class scope anyway and I don't want to "pollute" the namespace. How can I enable the ADL so that it works in the constructor initialization list?

3

There are 3 best solutions below

0
On BEST ANSWER

You can solve this directly from within the initialiser list, by using a lambda expression: it allows you to write the required helper function inline, and that helper function can contain using std::abs;.

template<typename T>
struct Foo
{
    T _data;

    Foo(T data):
        _data([&](){ using std::abs; return abs(data); }())
    {}
};
3
On

You can create a free or static local helper function and allow ADL to ocurr in there:

template <typename T>
struct Foo
{
    T _data;

    Foo(T data):
        _data(abs(data))
    {}

    template <typename X>
    using delete_reference = typename std::remove_reference<X>::type;

    template <typename U>
    static delete_reference<U> abs(U&& x)
    {
        using std::abs;
        return abs(std::forward<U>(x));
    }
};
1
On

Use a helper function:

namespace detail
{
    template <typename Arg>
    auto invoke_abs(Arg&& arg)
    {
        using std::abs;
        return abs(std::forward<Arg>(arg));
    }
}

Foo(T data)
    : _data{detail::invoke_abs(std::forward<T>(data))}
{ }