Vấn đề họ đang cảnh báo bạn về là trong C++ 14, điều này sẽ làm việc:
void call(void (*f)())
{
f();
}
void func() noexcept {}
int main(int argc, char* argv[])
{
call(&func);
return 0;
}
nhưng trong C++ 17, bạn sẽ cần phải thay đổi tuyên bố call
là:
void call(void (*f)() noexcept)
{
f();
}
Vì bạn đã xác định call
làm mẫu, bạn không cần phải lo lắng về điều này. Tuy nhiên, nó có thể gây ra vấn đề cho bạn bởi vì loại suy đoán đang thay đổi, điều này thường không xảy ra.
Ví dụ, mã này sẽ biên dịch trong C++ 14 nhưng không phải C++ 17:
void foo() noexcept {}
void bar() {}
template <typename F>
void call(bool b, F f1, F f2)
{
if (b)
f1();
else
f2();
}
void foobar(bool b)
{
call(b, &foo, &bar);
}
Trong C++ 14, các loại foo
và bar
đều giống nhau, nhưng chúng khác nhau trong C++ 17, có nghĩa là độ phân giải mẫu sẽ thất bại. Các thông báo lỗi trong gcc 7.2 với cờ -std=c++1z
là:
note: template argument deduction/substitution failed:
note: deduced conflicting types for parameter 'F' ('void (*)() noexcept' and 'void (*)()')
Trong ví dụ bạn đã đưa ra, không có vấn đề và bạn sẽ không có một vấn đề biên dịch trong C++ 14 hoặc C++ 17 chế độ. Nếu mã phức tạp hơn ví dụ ở đây (ví dụ tương tự như các ví dụ tôi đã đưa ra ở trên), bạn có thể gặp phải một số vấn đề về trình biên dịch. Dường như bạn có một trình biên dịch gần đây; thử biên dịch với -std=c++1z
và xem có cảnh báo hoặc lỗi hay không.
Nếu 'cuộc gọi' hoàn toàn nằm trong dự án của bạn, điều đó không quan trọng. Nó chỉ quan trọng trong trường hợp hai đơn vị dịch thuật khác nhau sử dụng nó, trong đó một đơn vị dịch được biên dịch với C++ 17 và một đơn vị không được dịch. Kể từ đó, vì 'call' là một hàm mẫu, nó có thể sẽ không có tác động lớn như vậy ngoài việc có định nghĩa phụ trong tệp thực thi cuối cùng. –
@ DanielH Không phải là tôi muốn nói chuyện với Barry, ở trên, nhưng nếu bạn đang biên soạn một dự án với -wError, thì "cảnh báo vô hại" đó sẽ khiến chương trình không biên dịch, mặc dù là chính xác. Điều đó quan trọng. – markt1964
@ markt1964 Trong bài viết chỉ '-Wall' được sử dụng. Nếu bạn biên dịch với '-Werror' hoặc cố gắng tránh lỗi trình biên dịch (đó là một ý tưởng hay), thì có, bạn sẽ có một vấn đề. Một trong đó có thể, có lẽ, tốt nhất được giải quyết bằng cách thêm '-Wno-noexcept-type', tùy thuộc vào hoàn cảnh. –