2

我正在编写一个递归函数,其结束条件由模板参数确定。我正在使用boost::enable_ifandboost::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>();
    }

为什么是这样?当实例化发生时(in main),编译器已经看到了这两个函数,不应该关心谁先排队。至少我是这么想的。

4

2 回答 2

4

你说

到实例化发生时(主要),编译器已经看到了这两个函数,不应该关心谁先排队。

这不是真的,我认为这就是让你绊倒的原因。在 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版本是可见的,并且会在需要时启动。

于 2013-06-08T19:26:52.713 回答
1

事实上,您的函数是模板,您对此感到困惑。这与它没有任何关系。以下内容也无法编译,原因相同。

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

void foo(char const*)
{
}

int main()
{
  foo(42);
}

订单很重要。

于 2013-06-10T17:50:35.810 回答