Tại sao một chuyên môn mẫu một phần trên một lớp mẫu phù hợp mơ hồ với một chuyên môn một phần khác mà không phù hợp với mẫu?


8

Câu hỏi có thể quá khó để mô tả trong câu trong tiêu đề, nhưng đây là một ví dụ tối thiểu:

#include <iostream>
#include <type_traits>

template <class T, class U, class Enabler>
struct my_trait : std::false_type
{};

template <class T, class U>
struct my_trait<T, U, 
                std::enable_if_t<std::is_same<T, U>::value>> : std::true_type
{};

template <class T>
class temped
{};

template <class T>
struct my_trait<temped<T>, temped<T>, void> : std::false_type
{};

template <class T, class U>
using trait_t = my_trait<T, U, void>;

int main()
{
    std::cout << std::boolalpha;
    std::cout << trait_t<int, float>::value << std::endl;   // false
    std::cout << trait_t<int, int>::value << std::endl;     // true

    // Compilation error: Ambiguous
    //std::cout << trait_t<temped<int>, temped<int>>::value << std::endl;
    return 0;    
}

( cũng có sẵn trên godbolt )

Về cơ bản, chúng ta có một lớp mẫu cơ sở my_traitlấy hai loại (và một loại giả cho mục đích chuyên môn hóa), với hai chuyên ngành một phần:

  • Khi hai loại giống nhau
  • Khi hai loại là khởi tạo tempedmẫu lớp cho cùng một loại

Ngẫu nhiên, chúng tôi đã dự kiến ​​chuyên môn hóa một phần thứ hai sẽ không mơ hồ với phần thứ nhất, vì nó cảm thấy "chuyên biệt hơn", đặt ra nhiều hạn chế hơn đối với các loại suy luận cho TUtrên mẫu cơ sở. Tuy nhiên, các trình biên dịch chính dường như đồng ý rằng chúng tôi đã sai với kỳ vọng của mình: tại sao nó không được coi là chuyên biệt hơn?


Câu trả lời:


1

Câu trả lời đã bị xóa của super super về cơ bản là đúng. std::enable_if_t<...>không voidtheo thứ tự một phần; như một loại phụ thuộc về nguyên tắc nó có thể là một cái gì đó hoàn toàn tùy ý. Nó có hiệu quả được coi là một loại hoàn toàn độc đáo cho mục đích đặt hàng một phần.

Do kết quả của sự không phù hợp này, việc khấu trừ trong khi đặt hàng một phần thất bại ở cả hai hướng và các chuyên ngành không rõ ràng.


1
Nhưng nó không thực sự là một loại phụ thuộc khi đặt hàng một phần, phải không? Đó là std::enable_if_t<std::is_same<DummyT, DummyT>::value>nơi DummyTchỉ là "tổng hợp" về mặt lý thuyết nhưng là loại cụ thể ( [temp.func.order] / 3 ).
aschepler

Có lẽ một "loại duy nhất được tổng hợp" cũng ngụ ý rằng có thể có các chuyên ngành bổ sung sử dụng loại đó, ngay cả khi không có các chuyên ngành hiện có thể nhìn thấy có thể tạo ra sự khác biệt? Nhưng tiêu chuẩn có nói rằng bất cứ nơi nào?
aschepler

Tôi có thể thiếu quan điểm của bạn: std_enable_if_t<>cung cấp một chuyên môn hóa một phần ưa thích trong câu lệnh trait_t<int, int>::value, vì vậy có vẻ như nó được xem xét void(nếu không, có vẻ như biểu thức này sẽ đánh giá thành sai bằng cách chọn mẫu cơ sở). Mặt khác, tuyên bố trait_t<temped<int>, temped<int>>::valuedẫn đến một sự mơ hồ, mặc dù chuyên môn hóa một phần my_trait<temped<T>, temped<T>, void>mà chúng tôi hy vọng sẽ được chuyên môn hóa rõ ràng hơn voidloại.
Quảng cáo N

Có một vấn đề mở liên quan đến vấn đề này: wg21.link/CWG2160 Tuy nhiên, trong trường hợp đó, suy luận rõ ràng không thành công theo một hướng (?) Vì vậy tôi không thể điều hòa ví dụ đó với ví dụ này.
Brian

1
Và trong mọi trường hợp, câu trả lời "thực" cho câu hỏi của OP phải là: tiêu chuẩn không rõ ràng về điều này, vì vậy đừng viết mã như thế này cho đến khi tiêu chuẩn làm rõ nó.
Brian

0

Là vì

std::enable_if_t<std::is_same_v<temped<int>, temped<int>> 

quyết tâm để trống và sau đó bạn có

my_trait<temped<int>, temped<int>, void>::value 

định nghĩa một cách mơ hồ là đúng hay sai. Nếu bạn thay đổi loại enable_if giải quyết thành, hãy nói bool, mọi thứ sẽ biên dịch tốt


1
OP đang hỏi tại sao nó mơ hồ, trong bối cảnh chuyên môn hóa đặt hàng một phần mẫu. Nếu bạn thay đổi std::enable_if_t<*, bool>, thì nó sẽ đánh bại mục đích (vì nó thậm chí không được kích hoạt để chuyên môn hóa).
Rin Kaenbyou
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.