13

xem xét mã:Có pháp lý để phần chuyên variadic mẫu lớp bên trong với args từ mẫu variadic của một lớp bên ngoài

#include <iostream> 

template <class... Ts> 
struct outer { 
    template <class... ITs> 
    struct inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct inner<Ts..., ITs...> { 
     static constexpr bool value = true; 
    }; 
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<int, float, double, int>::value << std::endl; 
} 

mã biên dịch với kêu vang ++ nhưng không phải với g ++ nơi nó tạo ra một lỗi:

temp3.cc:11:11: error: parameter pack argument ‘Ts ...’ must be at the end of the template argument list

struct inner<Ts..., ITs...> { 
    ^

Vì tôi đã thiết lập here chuyên môn hóa một phần của lớp bên trong nên hợp pháp.

Edit: Đối với đầy đủ nó là giá trị thêm rằng kêu vang cho mã trên cảnh báo rằng ông có thể có một vấn đề với suy luận thông số nào được nêu ra làm việc đó mà không cần bất kỳ vấn đề ...

+0

Tôi không biết chính xác quy tắc, nhưng khi tôi gặp lỗi với loại phụ thuộc, hãy thêm 'typename' hoặc' template' trước khi nó giúp. Hãy thử 'struct inner Dani

+0

sau khi thêm 'typename' Tôi nhận được' temp3.cc:11:39: lỗi: đối số mẫu 1 không hợp lệ' –

+0

Cần lưu ý rằng kịch bản được yêu cầu vẫn có thể được thực hiện với một số mẫu siêu lập trình bổ sung ... http://coliru.stacked-crooked.com/a/0c6c643c8ff5809e (vâng, tôi biết đó không phải là câu hỏi nhưng thách thức của việc thực hiện nó là không thể tránh khỏi ...). –

Trả lời

8

Đây là một lỗi gcc . Đây là chuyên môn một phần hoàn toàn hợp lệ:

template <class... ITs> 
struct inner<Ts..., ITs...> { 
    static constexpr bool value = true; 
}; 

Gói thông số mẫu bị thiếu phải là cuối cùng và ITs... thỏa mãn điều đó. Nhưng Ts... không phải là một gói cần được suy luận ở đây, nó chỉ là một gói tham số cụ thể.

Hơn nữa, gcc biên dịch một số công thức tương đương:

template <class... Ts> 
struct X { 
    template <class... Us> 
    static void foo(Ts..., Us...) { } 
}; 

int main() { 
    X<int>::foo(1, 'c'); 
} 

và:

template <class... Us> 
struct A { }; 

template <class... Ts> 
struct X { 
    template <class... Us> 
    static void foo(A<Ts..., Us...>) { } 
}; 

int main() { 
    X<int>::foo(A<int, char>{}); 
} 

Đây là tương đương tốt được hình thành để dụ ban đầu của bạn.

+0

Tôi nghi ngờ rằng nhưng không chắc chắn nếu không có một số quy tắc đặc biệt cho bối cảnh chuyên môn bên trong một lớp mẫu. Đó có phải là lỗi đã biết không? –

+4

Tôi đồng ý rằng nó có ý nghĩa cho việc chuyên môn hóa một phần là hợp lệ, nhưng tôi không chắc chắn rằng các tiêu chuẩn như bằng văn bản cho phép nó. [14.5.5p8.5] nói * Nếu một đối số là một gói mở rộng (14.5.3), nó sẽ là đối số cuối cùng trong danh sách đối số mẫu *. Đó là một yêu cầu cụ thể về chuyên môn từng phần, vì vậy nó không áp dụng cho các ví dụ của bạn. Điều này trông giống như một vấn đề tiêu chuẩn hơn là một lỗi trình biên dịch cho tôi. – bogdan

+0

Bạn nên gửi báo cáo lỗi cho 'gcc'. Bạn đã làm chưa – Destructor

0

có thể đơn giản workaround nhưng hiệu quả truyền cảm hứng về Barry của câu trả lời:

#include <iostream> 

template <class... Ts> 
struct pack { }; 

template <class... Ts> 
struct outer { 
    template <class IT> 
    struct inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct inner<pack<Ts..., ITs...>> { 
     static constexpr bool value = true; 
    }; 
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<pack<int, float, double, int>>::value << std::endl; 
} 

(Nó vẫn tạo ra cảnh báo trong vang dù)

1

Cưỡi trên câu trả lời WF, vẫn giữ cùng chính như trong câu hỏi ban đầu:

#include <iostream> 

template <class... Ts> 
struct pack { }; 

template <class... Ts> 
class outer { 
    template <class IT> 
    struct _inner { 
     static constexpr bool value = false; 
    }; 

    template <class... ITs> 
    struct _inner<pack<Ts..., ITs...>> { 
     static constexpr bool value = true; 
    }; 
public: 
    template <class... ITs> 
    struct inner { 
     static constexpr bool value = _inner<pack<ITs...>>::value; 
    };  
}; 

int main() { 
    std::cout << outer<int, float, double>::inner<int, float, double, int>::value 
      << std::endl; 
} 

Nó vẫn tạo ra một cảnh báo trong kêu vang, bởi vì các phiên bản đặc biệt của _inner không thể suy ra nó ... ngoài danh sách của Ts ... , CNTT ... (trong struct _inner<pack<Ts..., ITs...>>) - tuy nhiên mã không yêu cầu IT được suy ra riêng biệt với danh sách Ts ..., CNTT ..., vì vậy điều này sẽ ổn.

Trong g ++ nó biên dịch mà không có cảnh báo.

Code: http://coliru.stacked-crooked.com/a/ae3b21dd847450b2

(Đối với một giải pháp mà không một lời cảnh báo cũng kêu vang: http://coliru.stacked-crooked.com/a/0c6c643c8ff5809e).

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