启用enable / disable_if函数对的顺序很重要吗?

时间:2013-06-08 18:59:32

标签: c++ boost

我正在编写一个递归函数,其结束条件由模板参数决定。我正在使用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中),编译器已经看到了这两个函数,并且不应该关心谁先排队。至少那是我的想法。

2 个答案:

答案 0 :(得分:4)

你说

  

当实例化发生时(在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版本可见,并在需要时启动。

答案 1 :(得分:1)

事实上,你的功能是模板,这让你感到困惑。这与它没有任何关系。以下也没有编译,出于同样的原因。

void foo(int)
{
  foo("");
}

void foo(char const*)
{
}

int main()
{
  foo(42);
}

订单很重要。