有没有办法让编译器在选择候选人时包含来自外部范围的函数?

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

考虑这个 class 和可变成员函数:

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

有没有办法将终止递归的空 add 重载放置在另一个范围内? 请忽略这是否通常是个好主意,我严格要求如何做到这一点,如果有的话。我想把它放在 impl像这样的命名空间:

namespace impl
{
    void add() {}
}

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

但是上面的代码在实例化时不起作用。当参数包为空时,编译器抱怨找不到 add 的匹配函数调用。

有没有办法使用一些 scope-hackery 来实现这个?

你可以这样做:

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...);
    }
};

如果 foo_impl 放置在单独的命名空间中,这也将起作用。

但是,您不能将其作为免费功能与 add() 一起使用。语言中成员函数和自由函数可以属于同一个重载集的唯一上下文是在重载运算符查找期间。这是因为名称查找规则和重载解析只能在名称查找之后发生,并且只能在该名称查找找到的函数集上进行。

如何使用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...);
  }
};