2017-12-08 25 views
8

Tôi có hai (hoặc nhiều hơn) mẫu mà mỗi mẫu có thể thích ứng với một tập hợp các lớp cụ thể, được xác định bằng một khái niệm. Để có thể làm cho hai mẫu có cùng tên, chúng phải là các chuyên môn.C++ khái niệm và chuyên môn về mẫu; làm thế nào để có được một lỗi biên dịch thân thiện với người dùng

template< typename T > 
struct pin_in { static_assert(always_false<T>::value, . . .); }; 

template< is_pin_in T > 
struct pin_in<T> . . . 

template< is_pin_in_out T > 
struct pin_in<T> . . . 

Điều này hoạt động khi một trong các chuyên môn phù hợp. Khi không khớp với mẫu cơ bản được chọn, và tôi nhận được xác nhận thất bại. Cơ chế hoạt động. Tôi yêu các khái niệm!

Nhưng thông báo lỗi tôi nhận được (GCC 7.2.0) trỏ đến xác nhận. Tôi có thể bằng cách nào đó làm cho mẫu cơ sở không được chọn, vì vậy tôi sẽ nhận được một thông báo lỗi cho biết rằng không có mẫu nào phù hợp với lớp đối số?

+0

Tại sao bạn không thể thêm thông báo (đối số thứ 2) vào xác nhận tĩnh? –

+0

Tất nhiên tôi có, đó là. . . Nhưng thông báo lỗi chính vẫn trỏ đến xác nhận, không phải là dòng gây ra lỗi đó. –

+0

Trình biên dịch đôi khi thêm một backtrace trong dạng _in instantiation của Object_ và _required từ đây_, nơi nó trỏ nơi các instantiation đã diễn ra. –

Trả lời

2

Hoan hô, tôi tìm thấy một giải pháp! Những gì bạn cần là phải có mẫu chính hạn chế:

template <class T> 
    requires is_pin_in<T> || is_pin_in_out<T> 
struct pin_in {}; 


template <is_pin_in T> 
struct pin_in<T> {}; 

template <is_pin_in_out T> 
struct pin_in<T> {}; 

Và bạn nhận được một thông điệp chẩn đoán tốt:

<source>: In function 'auto test()': 
29 : <source>:29:16: error: template constraint failure 
    pin_in<char> a; 
       ^
29 : <source>:29:16: note: constraints not satisfied 
7 : <source>:7:24: note: within 'template<class T> concept const bool is_pin_in<T> [with T = char]' 
constexpr concept bool is_pin_in = std::is_same_v<T, int>; 
         ^~~~~~~~~ 
7 : <source>:7:24: note: 'std::is_same_v' evaluated to false 
9 : <source>:9:24: note: within 'template<class T> concept const bool is_pin_in_out<T> [with T = char]' 
constexpr concept bool is_pin_in_out = std::is_same_v<T, unsigned>; 
         ^~~~~~~~~~~~~ 
9 : <source>:9:24: note: 'std::is_same_v' evaluated to false 
Compiler exited with result code 1 

tốt, thông điệp của tôi là với một số hạn chế giả, nhưng bạn sẽ có được điểm

+0

Nice! Các khái niệm để giải cứu. –

+0

Nhưng có một vấn đề nhỏ: giải pháp này được đóng lại theo nghĩa là tôi không thể bổ sung thêm một chuyên môn cho giả sử is_pin_foo whithout cũng thay đổi mẫu cơ bản. Nhưng một loại thẻ trong các lớp được chấp nhận có thể giải quyết điều đó. Nhưng điều đó có thể gây ra vấn đề ngược lại: một mẫu trang trí được viết sau này sẽ cần phải trang bị thêm các lớp hiện có với điểm đánh dấu của nó. Trừ khi nó sẽ liệt kê chúng trong yêu cầu ... Tôi sẽ chơi với cái này! –

+0

@WoutervanOoijen Tôi sẽ chỉ tạo ra một khái niệm có ý nghĩa cho 'pin_in'. Ví dụ. 'mẫu khái niệm constexpr bool is_any_pin_in = is_pin_in || is_pin_in_out ' – bolov

0

Hãy thử sử dụng tiêu chuẩn :: enable_if để xóa mẫu cơ sở khỏi độ phân giải quá tải. Một cái gì đó như thế này:

template< typename T > 
struct pin_in<typename std::enable_if<false>::type> {}; 

template< is_pin_in T > 
struct pin_in<typename std::enable_if<true>::type><T> . . . 

template< is_pin_in_out T > 
struct pin_in<typename std::enable_if<true>::type><T> . . . 
+0

Đó là loại những gì tôi đã lloking cho, nhưng nó cho một lỗi trên pin_in đầu tiên: 'pin_in không phải là một mẫu lớp' –

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