Biên dịch loại bỏ thời gian của nhánh if / other trong C ++


8

Trong mẫu mã sau, ifcâu lệnh phụ thuộc vào booltham số mẫu, là hằng số thời gian biên dịch. Trình biên dịch xử lý mã này khác nhau:

  • MSVC không thành công với lỗi liên kết (đó là những gì tôi mong đợi), vì hàm mẫu trong elsenhánh thiếu chuyên môn hóa cho truegiá trị tham số mẫu (mặc dù nó không bao giờ được gọi).

  • Cả GCC và Clang đều biên dịch mà không có vấn đề và hành vi trong thời gian chạy là chính xác. Điều này rõ ràng là vì họ đánh giá ifcâu lệnh tại thời điểm biên dịch và loại bỏ các nhánh không sử dụng trước khi liên kết.

Câu hỏi đặt ra là hành vi nào tuân thủ tiêu chuẩn (hoặc đó là hành vi không xác định và cả hai đều đúng theo cách riêng của họ)?

#include <iostream>

template<const bool condition>
struct Struct
{
    void print()
    {
        if (condition)
        {
            std::cout << "True\n";
        }
        else
        {
            printIfFalse();
        }
    }

private:
    void printIfFalse();
};

template <>
void Struct<false>::printIfFalse()
{
    std::cout << "False\n";
}

int main()
{
    Struct<true> withTrue{};
    withTrue.print();

    Struct<false> withFalse{};
    withFalse.print();

    return 0;
}

4
Xin chào, không phải những gì bạn đang tìm kiếm, nhưng bạn có thể nhìn vàoif constexpr
Martin Morterol

1
Cả hai trình biên dịch đều đúng. Về mặt giáo dục, đây là hành vi không xác định. Tiêu chuẩn C ++ không chỉ định những gì xảy ra ở đây.
Sam Varshavchik

@SamVarshavchik Thậm chí hơn về mặt giáo dục , đó là Hành vi không xác định (UB). Nhưng trong thế giới thực, đó là một lỗi hoặc nó hoạt động. Không có UB khi chạy.
tò mò

Câu trả lời:


11

Tất cả các trình biên dịch hoạt động chính xác.

Chương trình của bạn không được định dạng đúng, không cần chẩn đoán , vì bạn đang sử dụng Struct<true>::printIfFalsethông qua việc khởi tạo Struct<true>::print()yêu cầu từ cuộc gọi trong withTrue.print();. Một hàm được sử dụng bên ngoài câu lệnh bị loại bỏ phải có định nghĩa trong chương trình, xem [basic.def.odr] / 4 , nếu không, chương trình không được định dạng, không cần chẩn đoán .

Một câu lệnh bị loại bỏ là những gì bạn nhận được nếu bạn sử dụng if constexprtrong một mẫu và câu lệnh không nằm trong nhánh được chọn. Vì vậy, những gì bạn có thể làm để làm cho chương trình được hình thành tốt là sử dụng if constexprthay vì if. Đây là một tính năng của C ++ 17.

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.