Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive noexcept specification

Testing with g++ 4.9 and clang 3.4, why does this code not compile:

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);
}

But this code does:

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);
}

The f_helper function does not have to be defined, it just has to have the correct return type specified by way of decltype in that case.

The first code also compiles for 1 or 2 arguments, but once I try to call it with 3 or more, I get errors about no matching functions to call. The clang error for the first code is:

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.
like image 872
David Stone Avatar asked May 21 '14 02:05

David Stone


1 Answers

3.3.2/1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any)...

exception-specification is syntactically part of the declarator. Thus, the function name is not in scope within its own exception-specification.

like image 119
Igor Tandetnik Avatar answered Oct 27 '22 22:10

Igor Tandetnik