Home > Software engineering >  Is there a way to make the compiler include functions from outer scopes when picking a candidate?
Is there a way to make the compiler include functions from outer scopes when picking a candidate?

Time:01-02

Consider this class and variadic member function:

class foo
{
public:
    template<class C, class... Cs>
    void add(C&& c, Cs&&... cs)
    {
        ...
        
        add(cs...);
    }
private:
    void add(){ }
};

Is there a way to place the empty add overload that terminates the recursion inside another scope? Please ignore whether or not this is generally a good idea, I am strictly asking for how one could do it, if at all. I would like to place it inside an impl namespace like so:

namespace impl
{
    void add() {}
}

class foo
{
public:
    template<class C, class... Cs>
    void add(C&& c, Cs&&... cs)
    {
        ...
        
        using namespace impl;
        add(cs...);
    }
};

But the above code does not work when instatiated. The compiler complains that it can't find a matching function call for add when the parameter pack is empty.

Is there a way to achieve this using some scope-hackery?

CodePudding user response:

How about using if constexpr:

namespace impl { void add() {} }

class foo {
 public:
  template<class C, class... Cs>
  void add(C&& c, Cs&&... cs)
  {
    if constexpr (sizeof...(Cs) == 0)
      impl::add();
    else
      add(cs...);
  }
};

CodePudding user response:

You can do it like this:

class foo_impl
{
    protected:
    void add() {}
};

class foo : private foo_impl
{
    using foo_impl::add;
public:
    template<class C, class... Cs>
    void add(C&& c, Cs&&... cs)
    {
        add(cs...);
    }
};

This will also work if foo_impl is placed in a separate namespace.

However, you can't make it work with add() as a free function. The only context in the language where member functions and free functions can belong to the same overload set is during overloaded operator lookup. This is because of the name lookup rules and the fact that overload resolution can only take place after name lookup, and only on the set of functions found by that name lookup.

  • Related