Ленивый enable_if спит на работе?

С приведенным ниже определением я могу позвонить qget<0>() или же qget<1>() используя G ++ (4.7.2), но qget<2> или «выше» потерпит неудачу с no matching function ошибка. Clang ++ (3.2), тем не менее, терпит неудачу с любым из них. Я использовал ленивый enable_if как последнее средство; хотя я не думаю, что я должен нужно это. Я знаю, что код выглядит немного странно, но кто-нибудь может увидеть источник ошибки? (Boost предоставляет классы enable_if.)

template <typename T> struct Tid { typedef T type; };

template <unsigned I>
typename enable_if_c<(I==0),double>::type
qget()
{ return 0.0; }

template <unsigned I>
typename lazy_enable_if_c<(I!=0), Tid<decltype(qget<I-1>())>>::type
qget()
{ return qget<I-1>(); }

2

Решение

Когда вы объявляете функцию или шаблон функции, например, ret foo(A, B, C); или равнодушно как auto foo(A, B, C) -> ret;тогда foo это относится к только что объявленной сущности, которая находится вне области действия до так называемого декларатора. В вашем конкретном случае тип возвращаемого значения (будь то поздний тип возвращаемого значения или нет) всегда является частью объявления.

Это означает, что в вашей последней декларации имя qget в возвращаемом типе может ссылаться на предыдущую декларацию (случай для I==0) но никогда не может ссылаться на текущую декларацию. Вот почему qget<0> а также qget<1> найдены, но qget<2> нет: при попытке сформировать тип возвращаемого значения последнего, qget<1> не найден, потому что первая декларация является SFINAE’d, как и предполагалось, а вторая декларация является текущей декларацией, а не в области видимости. Ошибка приводит к SFINAE.

Мое обычное решение, когда это происходит (что я должен сказать, не так часто), заключается в использовании struct (как деталь реализации), потому что все функции-члены (и шаблоны функций-членов) объявляются внутри определения класса, начиная с открывающей скобки.

При этом вы все равно столкнетесь с трудностями, потому что даже если вы используете lazy_enable_if_c вы все еще нетерпеливо вычисляете тип qget<I - 1>() (в качестве параметра для lazy_enable_if_c) даже когда I является 0, Ленивая оценка идентичности указанного типа не спасет вас.

К сожалению, я не могу получить пример, работающий с использованием GCC 4.7.2, который настаивает на том, чтобы не завершать рекурсию даже при исправлении условия в I > 0 и используя ленивый результат (хотя обычно я использую 4.8), поэтому я не могу обещать вам, что мое решение может быть выполнено.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]