본문 바로가기
개발/C++ (98,03,11,14,17,20,23)

Modern C++ : std::Attributes (11, 14, 17, 20)

by snowoods 2025. 10. 10.

Modern C++

 

std::Attributes

 

개요

C++ Attributes는 코드에 메타데이터를 추가하는 표준화된 방법을 제공합니다. 이 메타데이터는 컴파일러가 경고를 생성하거나, 코드를 최적화하거나, 특정 규칙을 강제하는 데 사용될 수 있습니다. 속성은 [[attribute]] 구문을 사용하여 지정됩니다.

 

C++ 버전별 주요 키워드 도입 시기

  • C++11: [[noreturn]], [[carries_dependency]]
  • C++14: [[deprecated]]
  • C++17: [[fallthrough]], [[nodiscard]], [[maybe_unused]]
  • C++20: [[likely]], [[unlikely]], [[no_unique_address]]

 

내용 설명

  • [[nodiscard]]: 함수의 반환 값을 무시해서는 안 됨을 나타냅니다. 반환 값을 사용하지 않으면 컴파일러가 경고를 발생시킵니다. 함수, 열거형, 구조체/클래스에 적용할 수 있습니다.
  • [[deprecated]]: 함수, 클래스, 변수 등이 더 이상 사용되지 않음을 표시합니다. 사용 시 컴파일러 경고가 발생하며, 대체할 기능을 문자열로 명시할 수 있습니다.
  • [[maybe_unused]]: 사용되지 않는 변수나 매개변수에 대한 컴파일러 경고를 표시하지 않도록 합니다.
  • [[fallthrough]]: switch 문에서 의도적으로 break 없이 다음 case로 넘어가도록 할 때 컴파일러 경고를 방지합니다.
  • [[likely]], [[unlikely]]: (C++20) 특정 코드 경로의 실행 가능성을 컴파일러에 알려주어 분기 예측 최적화를 돕습니다.

 

예제 코드

#include <iostream>

// [[nodiscard]] : 함수의 반환값을 무시하면 경고가 발생합니다.
[[nodiscard]] int get_value1()
{
    return 1;
}

// 열거형 자체에 nodiscard를 붙일 수 있습니다.
enum class [[nodiscard]] ReturnCodes{OK, NoData, Error};

// 구조체나 클래스에도 적용 가능합니다.
struct [[nodiscard]] Item
{
};

// [[deprecated]] : 해당 함수가 곧 사라질 예정임을 알립니다.
// 대체 함수를 문자열로 알려줄 수 있습니다.
[[deprecated("Use func2()")]] void func1()
{
}

// [[maybe_unused]] : 사용되지 않을 수 있는 변수나 함수에 대한 경고를 무시합니다.
[[maybe_unused]] double run(double d)
{
    return 2.0 * d;
}

int main()
{
    // get_value1(); // 경고: 'nodiscard' 속성으로 선언된 함수 'get_value1'의 반환 값을 무시합니다.
    func1();      // 경고: 'func1'은 사용되지 않는 선언입니다: Use func2()
    // run(11.0); // 반환 값을 사용하지 않아도 경고가 발생하지 않습니다.

    int alternative = get_value1();
    switch (alternative)
    {
        // [[likely]] : case 1이 실행될 확률이 높다고 컴파일러에 알립니다.
        [[likely]] case 1 :
            std::cout << "Case 1 likely\n";
            [[fallthrough]]; // [[fallthrough]] : 의도적으로 break를 생략했음을 알립니다.
        [[likely]] case 2:
        {
            std::cout << "Case 1 and 2\n";
            break;
        }
    default:
        std::cout << "Default\n";
    }

    return 0;
}

실행 결과

Case 1 likely
Case 1 and 2

 

Note: 컴파일러는 [[nodiscard]][[deprecated]] 속성이 붙은 코드를 사용하면 경고를 출력합니다. 실행 결과는 경고와는 별개로 정상적으로 출력됩니다.

활용팁

  • API 설계: [[nodiscard]]를 사용하여 중요한 반환 값을 클라이언트 코드가 놓치지 않도록 강제할 수 있습니다. (예: 오류 코드, 리소스 핸들)
  • 코드 리팩토링: [[deprecated]]를 사용하여 기존 코드를 점진적으로 개선하고, 이전 API 사용자에게 마이그레이션 경로를 명확하게 안내할 수 있습니다.
  • 가독성 및 유지보수: [[fallthrough]], [[maybe_unused]] 등은 코드의 의도를 명확히 하여 다른 개발자가 코드를 이해하고 유지보수하기 쉽게 만듭니다.
  • 성능 최적화: [[likely]], [[unlikely]]를 사용하여 컴파일러에게 분기 예측에 대한 힌트를 제공함으로써 미세한 성능 향상을 기대할 수 있습니다. (주로 성능에 민감한 코드에서 사용)