2012-02-29 37 views
5

Tôi chỉ đang cố gắng để hack một số nhị phân là operator ""_b, nhưng bị kẹt cố gắng chấm dứt đệ quy. Làm thế nào để xác định một hàm có thể được gọi bằng cách sử dụng một danh sách tham số mẫu trống rỗng, không xung đột với quá tải gói tham số? Sau đó, cảm hứng: phù hợp với việc mở rộng gói sản phẩm nào đó để một cái gì đó wacky.Việc mở rộng gói giá trị trống có khớp với gói loại hoặc tham số loại tùy chọn không?

Nhưng GCC than phiền rằng các loại không tồn tại của danh sách đối số trống không đồng ý với các loại danh sách tham số không bắt buộc. Có phải nó phải hoạt động theo cách này?

template< char head, char ... tail > 
constexpr unsigned long long parse_binary() { 
    return ((head - '0') << sizeof ... (tail)) 
     + parse_binary< tail ... >(); // Error: no overload for termination. 
} 

template< typename = void > // I want this to match an empty pack of chars. 
// template< short = 0 > // even this would do. 
constexpr unsigned long long parse_binary() { 
    return 0; 
} 

template< char ... digits > 
constexpr unsigned long long operator ""_b() { 
    return parse_binary< digits ... >(); 
} 

#include <iostream> 

int main() { 
    std::cout << 010101_b << '\n'; 
} 

Lưu ý: Câu hỏi không được triển khai operator ""_b. Vấn đề đó có thể được giải quyết bằng cách mở rộng gói vào danh sách tham số và chuyển các loại std::integral_constant xung quanh.

Lưu ý 2: Mã này thực sự không hoạt động với điều chỉnh nhỏ; xem câu trả lời của tôi dưới đây. Nhưng điều đó không trực tiếp giải quyết câu hỏi. Hmm, có lẽ tôi nên chỉnh sửa thông tin này thay vì trả lời…

+0

Nói chung bạn có thể chấm dứt đệ quy bằng cách làm cho mẫu gốc 'mẫu ', và sử dụng 'template ' để chấm dứt - nhưng tôi đoán đó không phải là những gì bạn đang hỏi. –

+1

@ BjörnPollex Không, sau đó vượt qua hai đối số sẽ không rõ ràng. Các gói được phép để trống. Một 'mẫu < char head >' và một 'mẫu ' sẽ làm các trick, nhưng yeah, đó không phải là câu hỏi. – Potatoswatter

Trả lời

0

Không tin chính thức về việc tuân thủ khó khăn như vậy khớp, nhưng mã đã cho làm hoạt động nếu hai tình trạng quá tải được chuyển đổi.

Thứ hai, quá tải kết thúc không hiển thị cho lần đầu tiên bởi vì đầu tiên giải quyết tên tại thời điểm định nghĩa mẫu. Chỉ các cuộc gọi chức năng phụ thuộc vào tham số mẫu mới được tra cứu cho đến khi thời gian khởi tạo.

Chỉ cần được rõ ràng, làm việc này:

template< typename = void > // Define this one first! 
constexpr unsigned long long parse_binary() { 
    return 0; 
} 

template< char head, char ... tail > 
constexpr unsigned long long parse_binary() { 
    return ((head - '0') << sizeof ... (tail)) 
     + parse_binary< tail ... >(); // Bingo: overload found. 
} 
+0

iirc trong C++ 11 chúng ta có một dấu đầu dòng rõ ràng rằng tên hàm phụ thuộc nếu nó là một id mẫu và một trong các đối số mẫu phụ thuộc. bây giờ để biết rằng nó là một id mẫu trình biên dịch đầu tiên đã tìm nó lên đến một mẫu nhưng tôi zhink soesnt ngăn cản một thời gian tra cứu thời gian thứ hai. –

+0

yep Tôi đã xác minh rằng đây là lỗi GCC: "parse_binary < tail ... >()" cũng nên thực hiện tra cứu phụ thuộc tức thời của "parse_binary". –

+0

@ JohannesSchaub-litb: Thú vị! Bạn đã gửi lỗi? – Potatoswatter

4

Sẽ không tốt hơn nếu chấm dứt đệ quy tại một ký tự?

template<char Ch> 
constexpr unsigned long long parse_binary(){ 
    return Ch - '0'; 
}; 

// second head to disambiguate 
template< char head1, char head2, char ... tail > 
constexpr unsigned long long parse_binary() { 
    return ((head1 - '0') << sizeof ... (tail)+1) + parse_binary< head2, tail ... >(); 
} 

Trong mọi trường hợp, vấn đề là parse_binary cho zero chars cần phải được khai báo trước khi phiên bản variadic, như Clang độc đáo chỉ ra:

error: call to function 'parse_binary' that is neither visible in 
     the template definition nor found by argument-dependent lookup 

// call trace... 

note: 'parse_binary' should be declared prior to the call site 
     constexpr unsigned long long parse_binary() { 
+0

LOL. Tôi vừa viết câu trả lời của tôi cho Björn trước khi cuộn xuống đây. Như tôi đã nói trong lưu ý, đây là một câu hỏi về các gói tham số, không thực hiện các chữ nhị phân. Giải pháp thanh lịch là mở rộng gói trong danh sách tham số hàm. – Potatoswatter

+0

Ah, vâng, bạn không được phép mở rộng tập ứng viên quá tải trừ khi tên quá tải là ADL phụ thuộc vào tham số mẫu. Aha, kết hợp với bình luận của Luc trong trò chuyện, tôi nghĩ giờ tôi đã hiểu. – Potatoswatter

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