2013-06-08 5 views
2

Я пишу рекурсивную функцию, конечное условие которой определяется параметрами шаблона. Я использую boost::enable_if и boost::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>(); 
    } 

компилятор (г ++ 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) компилятор видел обе функции и не заботился о том, кто первым попал в очередь. По крайней мере, это то, что я думал.

ответ

4

Вы говорите

By the time the instantiation happens (in main) the compiler has seen both functions and shouldn't care who got in line first.

Это не так, и я думаю, что это то, что отключение вас. То, что было создано в основном, - это только 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 видна и ногами в случае необходимости.

+0

Подумав об этом еще немного, я думаю, что я смущен, потому что думал, что 'f' является зависимым именем, потому что это шаблон. Разве это не так? Если нет, то я полностью согласен, потому что тогда 'f ();' разрешается по определению шаблона, а не по его описанию позже. – SirGuy

+0

Нет, имя шаблона не является зависимым именем. Даже если бы это было так, то точкой инстанцирования была бы область первого 'f', и она по-прежнему не могла привязать' f' ко второму шаблону. – jrok

1

Вы смешиваетесь с тем, что ваши функции являются шаблонами. Это не имеет к этому никакого отношения. Следующее также не компилируется и по той же причине.

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

void foo(char const*) 
{ 
} 

int main() 
{ 
    foo(42); 
} 

Информация для заказа.

+0

Да, это все в двух словах – SirGuy

Смежные вопросы