2014-05-21 13 views
6

Testing với g ++ 4.9 và kêu vang 3.4, tại sao mã này không biên dịch:Recursive noexcept đặc điểm kỹ thuật

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

Nhưng mã này không:

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

Chức năng f_helper không nhất thiết phải được xác định, nó chỉ phải có kiểu trả về đúng được xác định theo cách của decltype trong trường hợp đó.

Mã đầu tiên cũng biên dịch cho 1 hoặc 2 đối số, nhưng khi tôi cố gắng gọi nó bằng 3 hoặc nhiều hơn, tôi gặp lỗi về không có hàm phù hợp để gọi. Các lỗi kêu vang cho mã đầu tiên là:

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. 
+0

Phiên bản với trình trợ giúp [không biên dịch] (http://coliru.stacked-crooked.com/a/126cee2269269e96) nếu bạn chuyển 4 tham số cho f. –

Trả lời

5

3.3.2/1 Điểm kê khai cho một tên là ngay sau khi declarator hoàn chỉnh của nó (khoản 8) và trước khi khởi tạo của nó (nếu có) ...

đặc điểm ngoại lệ là một phần cú pháp của người khai báo. Do đó, tên hàm không nằm trong phạm vi bên trong đặc tả riêng của nó.

+0

Mặc dù về mặt kỹ thuật tôi không thực sự gọi hàm này đệ quy, tôi gọi một hàm hoàn toàn khác được tạo ra từ cùng một khuôn mẫu, mà cuối cùng gọi định nghĩa hàm đơn đối số. Điều đó có thể giúp tôi không? –

+1

Tên của mẫu chức năng đó không nằm trong phạm vi tại điểm mà bạn đang cố gắng sử dụng. –

+0

@DavidStone Tôi nghĩ rằng nó có thể được tìm thấy thông qua ADL tuy nhiên? Điều này mở ra mọi thứ cho một hack, nơi bạn tạo ra một thực thi chức năng 'template' với một đối số giả từ cùng một' không gian tên', và xác định đối số công khai về mặt thực hiện nói trên. Không chắc chắn nếu điều này hoạt động. – Yakk

Các vấn đề liên quan