Рекурсивная спецификация noexcept

Тестирование с g++ 4.9 и clang 3.4, почему этот код не компилируется:

namespace {

template<typename T>
constexpr auto f(T && t) noexcept {
    return true;
}

template<typename T, typename... Ts>
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
    return f(ts...);
}

}   // namespace

int main() {
    f(true, 0, 5u);
}

Но этот код делает:

namespace {

template<typename T>
constexpr auto f(T && t) noexcept {
    return true;
}

template<typename T>
constexpr auto f_helper(T && t) noexcept(noexcept(f(t))) {
    return f(t);
}

template<typename T, typename... Ts>
constexpr auto f_helper(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
    return f(ts...);
}

template<typename T, typename... Ts>
constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f_helper(ts...))) {
    return f(ts...);
}

}   // namespace

int main() {
    f(true, 0, 5u);
}

Функция f_helper не должна быть определена, она просто должна иметь правильный тип возвращаемого значения, указанный в этом случае посредством decltype.

Первый код также компилируется для 1 или 2 аргументов, но как только я пытаюсь вызвать его с 3 или более, я получаю ошибки об отсутствии соответствующих функций для вызова. Ошибка лягушки для первого кода:

source/main.cpp:9:59: error: call to function 'f' that is neither visible in the template definition nor
      found by argument-dependent lookup
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                                                                 ^
source/main.cpp:9:17: note: in instantiation of exception specification for 'f<bool, int, unsigned int>'
      requested here
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                       ^
source/main.cpp:16:3: note: in instantiation of function template specialization '<anonymous
      namespace>::f<bool, int, unsigned int>' requested here
                f(true, 0, 5u);
                ^
source/main.cpp:9:17: note: 'f' should be declared prior to the call site
        constexpr auto f(T && t, Ts && ... ts) noexcept(noexcept(f(ts...))) {
                       ^
1 error generated.

1 ответ

Решение

3.3.2/1 Точка декларации для имени находится сразу после его полного декларатора (пункт 8) и до его инициализатора (если есть)...

Спецификация исключения является синтаксической частью объявления. Таким образом, имя функции не входит в область действия своей собственной спецификации исключений.

Другие вопросы по тегам