Tôi đã lãng phí vô số giờ để xác định vấn đề với gcc. Tôi muốn kiểm tra cơ sở mã của chúng tôi với một trình biên dịch khác để tìm thêm các cảnh báo rằng Clang có thể đã bị bỏ qua. Tôi đã bị sốc rằng thực tế một nửa của dự án dừng lại để biên dịch do sự thất bại của mẫu khấu trừ đối số. Ở đây tôi đã cố gắng để câm trường hợp của tôi xuống phần đơn giản nhất của mã.Tất cả các phiên bản của cuộc đấu tranh GCC với mẫu có loại mặc định theo định nghĩa
#include <type_traits>
struct Foo
{ };
// This is a template function declaration, where second template argument declared without a default
template <typename T, typename>
void foo(const Foo & foo, T t);
// This is a template function definition; second template argument now has a default declared
template <typename T, typename = typename std::enable_if<1>::type>
void foo(const Foo & foo, T t)
{
}
int main(int argc, char ** argv)
{
foo(Foo{}, 1);
return 0;
}
Bỏ qua một 1
trong std::enable_if<1>
. Rõ ràng đó là một giá trị không đổi chỉ để không phức tạp những điều khi nó không quan trọng.
Đoạn mã biên dịch [1] với kêu vang (3.4 qua 4.0), icc (16, 17), Visual C++ (19.00.23506). Về cơ bản, tôi không thể tìm thấy bất kỳ trình biên dịch C++ 11 nào khác, ngoại trừ gcc (4.8 đến 7.1), không biên dịch đoạn mã này.
Câu hỏi đặt ra là ai đúng và ai sai ở đây? gcc có hoạt động theo tiêu chuẩn không?
Rõ ràng đây không phải là vấn đề quan trọng. Tôi có thể dễ dàng di chuyển std::enable_if
đến tuyên bố. Nạn nhân duy nhất sẽ là thẩm mỹ. Nhưng nó là tốt đẹp để có thể ẩn một 100 ký tự xấu xí dài std::enable_if
đoạn mã, mà không phải là ngay lập tức có liên quan cho người sử dụng chức năng thư viện, trong việc thực hiện.
Ví dụ trực tiếp trên godbolt.org.
Trên en.cppreference.com nó nói cho [đối số mẫu mặc định] (http://en.cppreference.com/w/cpp/language/template_parameters#Default_template_arguments) »Đối số mẫu mặc định xuất hiện trong các khai báo và định nghĩa được hợp nhất tương tự với các đối số hàm mặc định «. Đối với [đối số hàm mặc định] (http://en.cppreference.com/w/cpp/language/default_arguments) tôi tìm thấy »... được chỉ định bằng cách sử dụng cú pháp sau cho tham số trong danh sách tham số của khai báo hàm« . Nếu tôi giải thích điều này một cách chính xác, thì bạn * có * để có đối số mặc định trong khai báo. –
@HenriMenke, nó hoạt động cho các chức năng trong ** gcc **: https://godbolt.org/g/kXNbYi. Dường như ** gcc ** có tiêu chuẩn kép cho các chức năng và mẫu ... – GreenScape
@HenriMenke Xem ví dụ về 'template <...> lớp A' ở mức 14.1/10. Nó hoạt động như trong g ++, nhưng không phải nếu bạn thay thế một lớp với một hàm. –