提升启用/disable_if功能对的顺序重要吗?

Boost enable/disable_if function pair's order matters?

本文关键字:顺序 功能 启用 disable if      更新时间:2023-10-16

我正在编写一个递归函数,其结束条件由模板参数决定。我使用boost::enable_ifboost::disable_if将递归函数切换为空的基本情况(以防止讨厌的无限实例化循环)。
问题是,它似乎取决于我定义这些函数的顺序:

    #include <boost/utility.hpp>
    template <unsigned a, unsigned b>
    typename boost::disable_if_c<a == b>::type f()
    {
        f<a+1,b>();
    }
    template <unsigned a, unsigned b>
    typename boost::enable_if_c<a == b>::type f()
    {
    }
    int main()
    {
        f<0,5>();
    }

编译器(g++4.6)失败,报错:

    test.cpp:7:5: error: no matching function for call to ‘f()’
    test.cpp:7:5: note: candidate is:
    test.cpp:5:44: note: template<unsigned int a, unsigned int b> typename boost::disable_if_c<(a == b)>::type f()

由于某些原因,只有禁用的函数作为候选函数,未看到启用的函数。

如果我改变两个函数定义的顺序,它会编译有问题,没有警告:

    #include <boost/utility.hpp>
    template <unsigned a, unsigned b>
    typename boost::enable_if_c<a == b>::type f()
    {
    }
    template <unsigned a, unsigned b>
    typename boost::disable_if_c<a == b>::type f()
    {
        f<a+1,b>();
    }
    int main()
    {
        f<0,5>();
    }

为什么会这样?到实例化发生的时候(在main中),编译器已经看到了两个函数,不应该关心谁先进入行。至少我是这么想的。

你说

当实例化发生时(在main中),编译器已经看到了两个函数,不应该关心谁先进入行。

这不是真的,我认为这就是你犯错的原因。在main中实例化的只是f<0,5>,其余的实例化发生在调用它们的地方,在第一个f函数模板中。第二个是不可见的,所以它不能参与重载解析。

结果呢:

// imagine we're inside f<4,5> instantiation
template <unsigned a, unsigned b>
typename boost::disable_if_c<a == b>::type f()
{
    f<a+1,b>(); // <-- here we attempt to instantiate f<5,5> ...
                // but it gets disabled!
    // and there is no other f visible here, it's defined just below
}

如果你改变定义的顺序,enable_if版本是可见的,它在需要时启动。

由于函数是模板而混淆了。这跟这事一点关系都没有。由于同样的原因,下面的代码也不能编译。

void foo(int)
{
  foo("");
}
void foo(char const*)
{
}
int main()
{
  foo(42);
}

顺序很重要。